home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.006 / xemacs-1 / lib / xemacs-19.13 / lisp / modes / ada-mode.el < prev    next >
Encoding:
Text File  |  1995-08-22  |  115.9 KB  |  3,742 lines

  1. ;;; ada-mode.el - An Emacs major-mode for editing Ada source.
  2. ;;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
  3.  
  4. ;;; Authors: Markus Heritsch <Markus.Heritsch@studbox.uni-stuttgart.de>
  5. ;;;          Rolf Ebert      <ebert@inf.enst.fr>
  6.  
  7. ;;; This file is part of GNU Emacs.
  8.  
  9. ;; GNU Emacs is free software; you can redistribute it and/or modify
  10. ;; it under the terms of the GNU General Public License as published by
  11. ;; the Free Software Foundation; either version 2, or (at your option)
  12. ;; any later version.
  13.  
  14. ;; GNU Emacs is distributed in the hope that it will be useful,
  15. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. ;; GNU General Public License for more details.
  18.  
  19. ;; You should have received a copy of the GNU General Public License
  20. ;; along with GNU Emacs; see the file COPYING.  If not, write to
  21. ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  
  23. ;;; This mode is a complete rewrite of a major mode for editing Ada 83
  24. ;;; and Ada 95 source code under Emacs-19.  It contains completely new
  25. ;;; indenting code and support for code browsing (see ada-xref).
  26.  
  27.  
  28. ;;; USAGE
  29. ;;; =====
  30. ;;; Emacs should enter ada-mode when you load an ada source (*.ad[abs]).
  31. ;;;
  32. ;;; When you have entered ada-mode, you may get more info by pressing
  33. ;;; C-h m. You may also get online help describing various functions by:
  34. ;;; C-h d <Name of function you want described>
  35.  
  36.  
  37. ;;; HISTORY
  38. ;;; =======
  39. ;;; The first Ada mode for GNU Emacs was written by V. Broman in
  40. ;;; 1985. He based his work on the already existing Modula-2 mode.
  41. ;;; This was distributed as ada.el in versions of Emacs prior to 19.29.
  42. ;;;
  43. ;;; Lynn Slater wrote an extensive Ada mode in 1989. It consisted of
  44. ;;; several files with support for dired commands and other nice
  45. ;;; things. It is currently available from the PAL
  46. ;;; (wuarchive.wustl.edu:/languages/ada) as ada-mode-1.06a.tar.Z.
  47. ;;;
  48. ;;; The probably very first Ada mode (called electric-ada.el) was
  49. ;;; written by Steven D. Litvintchouk and Steven M. Rosen for the
  50. ;;; Gosling Emacs. L. Slater based his development on ada.el and
  51. ;;; electric-ada.el.
  52. ;;;
  53. ;;; The current Ada mode is a complete rewrite by M. Heritsch and
  54. ;;; R. Ebert.  Some ideas from the ada-mode mailing list have been
  55. ;;; added.  Some of the functionality of L. Slater's mode has not
  56. ;;; (yet) been recoded in this new mode.  Perhaps you prefer sticking
  57. ;;; to his version.
  58.  
  59.  
  60. ;;; KNOWN BUGS
  61. ;;; ==========
  62. ;;;
  63. ;;; In the presence of comments and/or incorrect syntax
  64. ;;; ada-format-paramlist produces weird results.
  65. ;;;
  66. ;;; Indenting of some tasking constructs is still buggy.
  67. ;;; -------------------
  68. ;;;   For tagged types the problem comes from the keyword abstract:
  69.  
  70. ;;;   type T2 is abstract tagged record
  71. ;;;   X : Integer;
  72. ;;;   Y : Float;
  73. ;;;   end record;
  74. ;;; -------------------    
  75. ;;; In Emacs FSF 19.28, ada-mode will correctly indent comments at the
  76. ;;; very beginning of the buffer (_before_ any code) when I go M-; but
  77. ;;; when I press TAB I'd expect the comments to be placed at the beginning
  78. ;;; of the line, just as the first line of _code_ would be indented.
  79.  
  80. ;;; This does not happen but the comment stays put :-( I end up going 
  81. ;;; M-; C-a M-\
  82. ;;; -------------------
  83. ;;; package Test is
  84. ;;;    -- If I hit return on the "type" line it will indent the next line
  85. ;;;    -- in another 3 space instead of heading out to the "(". If I hit
  86. ;;;    -- tab or return it reindents the line correctly but does not initially.
  87. ;;;    type Wait_Return is (Read_Success, Read_Timeout, Wait_Timeout,
  88. ;;;       Nothing_To_Wait_For_In_Wait_List);
  89. ;;;
  90. ;;;    -- The following line will be wrongly reindented after typing it in after
  91. ;;;    -- the initial indent for the line was correct after type return after
  92. ;;;    -- this line. Subsequent lines will show the same problem.
  93. ;;; Unused:    constant Queue_ID := 0;
  94. ;;; -------------------
  95. ;;; -- If I do the following I get 
  96. ;;; -- "no matching procedure/function/task/declare/package"
  97. ;;; -- when I do return (I reverse the mappings of ^j and ^m) after "private".
  98. ;;; package Package1 is
  99. ;;;    package Package1_1 is
  100. ;;;       type The_Type is private;
  101. ;;;       private
  102. ;;; -------------------
  103. ;;; -- But what about this:
  104. ;;; package G is
  105. ;;;    type T1 is new Integer;
  106. ;;;    type T2 is new Integer;  --< incorrect, correct if subtype
  107. ;;;    package H is
  108. ;;;       type T3 is new Integer;
  109. ;;;    type                     --< Indentation is incorrect
  110. ;;; -------------------
  111.  
  112.  
  113.  
  114. ;;; CREDITS
  115. ;;; =======
  116. ;;;
  117. ;;; Many thanks to
  118. ;;;    Philippe Warroquiers (PW) <philippe@cfmu.eurocontrol.be> in particular,
  119. ;;;    woodruff@stc.llnl.gov (John Woodruff)
  120. ;;;    jj@ddci.dk (Jesper Joergensen)
  121. ;;;    gse@ocsystems.com (Scott Evans)
  122. ;;;    comar@LANG8.CS.NYU.EDU (Cyrille Comar)
  123. ;;;    and others for their valuable hints.
  124.  
  125. ;;;--------------------
  126. ;;;    USER OPTIONS
  127. ;;;--------------------
  128.  
  129. ;; ---- configure indentation
  130.  
  131. (defvar ada-indent 3
  132.   "*Defines the size of Ada indentation.")
  133.  
  134. (defvar ada-broken-indent 2
  135.   "*# of columns to indent the continuation of a broken line.")
  136.  
  137. (defvar ada-label-indent -4
  138.   "*# of columns to indent a label.")
  139.  
  140. (defvar ada-stmt-end-indent 0
  141.   "*# of columns to indent a statement end keyword in a separate line.
  142. Examples are 'is', 'loop', 'record', ...")
  143.  
  144. (defvar ada-when-indent 3
  145.   "*Defines the indentation for 'when' relative to 'exception' or 'case'.")
  146.  
  147. (defvar ada-indent-record-rel-type 3
  148.   "*Defines the indentation for 'record' relative to 'type' or 'use'.")
  149.  
  150. (defvar ada-indent-comment-as-code t
  151.   "*If non-nil, comment-lines get indented as ada-code.")
  152.  
  153. (defvar ada-indent-is-separate t
  154.   "*If non-nil, 'is separate' or 'is abstract' on a separate line are
  155. indented.")
  156.  
  157. (defvar ada-indent-to-open-paren t
  158.   "*If non-nil, following lines get indented according to the innermost
  159. open parenthesis.")
  160.  
  161. (defvar ada-search-paren-char-count-limit 3000
  162.   "*Search that many characters for an open parenthesis.")
  163.  
  164.  
  165. ;; ---- other user options
  166.  
  167. (defvar ada-tab-policy 'indent-auto
  168.   "*Control behaviour of the TAB key.
  169. Must be one of 'indent-rigidly, 'indent-auto, 'gei, 'indent-af or 'always-tab.
  170.  
  171. 'indent-rigidly : always adds ada-indent blanks at the beginning of the line.
  172. 'indent-auto    : use indentation functions in this file.
  173. 'gei            : use David Kσgedal's Generic Indentation Engine.
  174. 'indent-af      : use Gary E. Barnes' ada-format.el
  175. 'always-tab     : do indent-relative.")
  176.  
  177. (defvar ada-move-to-declaration nil
  178.   "*If non-nil, ada-move-to-start moves point to the subprog-declaration,
  179. not to 'begin'.")
  180.  
  181. (defvar ada-spec-suffix ".ads"
  182.   "*Suffix of Ada specification files.")
  183.  
  184. (defvar ada-body-suffix ".adb"
  185.   "*Suffix of Ada body files.")
  186.  
  187. (defvar ada-language-version 'ada95
  188.   "*Do we program in 'ada83 or 'ada95?")
  189.  
  190. (defvar ada-case-keyword 'downcase-word
  191.   "*downcase-word, upcase-word, ada-loose-case-word or capitalize-word
  192. to adjust ada keywords case.")
  193.  
  194. (defvar ada-case-identifier 'ada-loose-case-word
  195.   "*downcase-word, upcase-word, ada-loose-case-word or capitalize-word
  196. to adjust ada identifier case.")
  197.  
  198. (defvar ada-case-attribute 'capitalize-word
  199.   "*downcase-word, upcase-word, ada-loose-case-word or capitalize-word
  200. to adjust ada identifier case.")
  201.  
  202. (defvar ada-auto-case t
  203.   "*Non-nil automatically changes casing of preceeding word while typing.
  204. Casing is done according to ada-case-keyword and ada-case-identifier.")
  205.  
  206. (defvar ada-clean-buffer-before-saving  nil
  207.   "*If non-nil, remove-trailing-spaces and untabify buffer before saving.")
  208.  
  209. (defvar ada-mode-hook nil
  210.   "*List of functions to call when Ada Mode is invoked.
  211. This is a good place to add Ada environment specific bindings.")
  212.  
  213. (defvar ada-external-pretty-print-program "aimap"
  214.   "*External pretty printer to call from within Ada Mode.")
  215.  
  216. (defvar ada-tmp-directory "/tmp/"
  217.   "*Directory to store the temporary file for the Ada pretty printer.")
  218.  
  219. (defvar ada-fill-comment-prefix "-- "
  220.   "*This is inserted in the first columns when filling a comment paragraph.")
  221.  
  222. (defvar ada-fill-comment-postfix " --"
  223.   "*This is inserted at the end of each line when filling a comment paragraph
  224. with ada-fill-comment-paragraph postfix.")
  225.  
  226. (defvar ada-krunch-args "0"
  227.   "*Argument of gnatk8, a string containing the max number of characters.
  228. Set to 0, if you dont use crunched filenames.")
  229.  
  230. ;;; ---- end of user configurable variables
  231.  
  232.  
  233. (defvar ada-mode-abbrev-table nil
  234.   "Abbrev table used in Ada mode.")
  235. (define-abbrev-table 'ada-mode-abbrev-table ())
  236.  
  237. (defvar ada-mode-map ()
  238.   "Local keymap used for ada-mode.")
  239.  
  240. (defvar ada-mode-syntax-table nil
  241.   "Syntax table to be used for editing Ada source code.")
  242.  
  243. (defvar ada-mode-symbol-syntax-table nil
  244.   "Syntax table for Ada, where `_' is a word constituent.")
  245.  
  246. (defconst ada-83-keywords
  247.   "\\<\\(abort\\|abs\\|accept\\|access\\|all\\|and\\|array\\|\
  248. at\\|begin\\|body\\|case\\|constant\\|declare\\|delay\\|delta\\|\
  249. digits\\|do\\|else\\|elsif\\|end\\|entry\\|exception\\|exit\\|for\\|\
  250. function\\|generic\\|goto\\|if\\|in\\|is\\|limited\\|loop\\|mod\\|\
  251. new\\|not\\|null\\|of\\|or\\|others\\|out\\|package\\|pragma\\|\
  252. private\\|procedure\\|raise\\|range\\|record\\|rem\\|renames\\|\
  253. return\\|reverse\\|select\\|separate\\|subtype\\|task\\|terminate\\|\
  254. then\\|type\\|use\\|when\\|while\\|with\\|xor\\)\\>"
  255.   "regular expression for looking at Ada83 keywords.")
  256.  
  257. (defconst ada-95-keywords
  258.   "\\<\\(abort\\|abs\\|abstract\\|accept\\|access\\|aliased\\|\
  259. all\\|and\\|array\\|at\\|begin\\|body\\|case\\|constant\\|declare\\|\
  260. delay\\|delta\\|digits\\|do\\|else\\|elsif\\|end\\|entry\\|\
  261. exception\\|exit\\|for\\|function\\|generic\\|goto\\|if\\|in\\|\
  262. is\\|limited\\|loop\\|mod\\|new\\|not\\|null\\|of\\|or\\|others\\|\
  263. out\\|package\\|pragma\\|private\\|procedure\\|protected\\|raise\\|\
  264. range\\|record\\|rem\\|renames\\|requeue\\|return\\|reverse\\|\
  265. select\\|separate\\|subtype\\|tagged\\|task\\|terminate\\|then\\|\
  266. type\\|until\\|use\\|when\\|while\\|with\\|xor\\)\\>"
  267.   "regular expression for looking at Ada95 keywords.")
  268.  
  269. (defvar ada-keywords ada-95-keywords
  270.   "regular expression for looking at Ada keywords.")
  271.  
  272. (defvar ada-ret-binding nil
  273.   "Variable to save key binding of RET when casing is activated.")
  274.  
  275. (defvar ada-lfd-binding nil
  276.   "Variable to save key binding of LFD when casing is activated.")
  277.  
  278. ;;; ---- Regexps to find procedures/functions/packages
  279.  
  280. (defconst ada-ident-re 
  281.   "[a-zA-Z0-9_\\.]+"
  282.   "Regexp matching Ada identifiers.")
  283.  
  284. (defvar ada-procedure-start-regexp
  285.   "^[ \t]*\\(procedure\\|function\\|task\\)[ \t\n]+\\([a-zA-Z0-9_\\.]+\\)"
  286.   "Regexp used to find Ada procedures/functions.")
  287.  
  288. (defvar ada-package-start-regexp
  289.   "^[ \t]*\\(package\\)"
  290.   "Regexp used to find Ada packages")
  291.  
  292.  
  293. ;;; ---- regexps for indentation functions
  294.  
  295. (defvar ada-block-start-re
  296.   "\\<\\(begin\\|select\\|declare\\|private\\|or\\|generic\\|\
  297. exception\\|loop\\|else\\|\
  298. \\(\\(limited\\|abstract\\|tagged\\)[ \t]+\\)*record\\)\\>"
  299.   "Regexp for keywords starting ada-blocks.")
  300.  
  301. (defvar ada-end-stmt-re
  302.   "\\(;\\|=>\\|^[ \t]*separate[ \t]+([a-zA-Z0-9_\\.]+)\\|\
  303. \\<\\(begin\\|else\\|record\\|loop\\|select\\|do\\|\
  304. ^[ \t]*package[ \ta-zA-Z0-9_\\.]+is\\|\
  305. ^[ \t]*exception\\|declare\\|generic\\|private\\)\\>\\)"
  306.   "Regexp of possible ends for a non-broken statement.
  307. 'end' means that there has to start a new statement after these.")
  308.  
  309. (defvar ada-loop-start-re
  310.   "\\<\\(for\\|while\\|loop\\)\\>"
  311.   "Regexp for the start of a loop.")
  312.  
  313. (defvar ada-subprog-start-re
  314.   "\\<\\(procedure\\|protected\\|package[ \t]+body\\|function\\|\
  315. task\\|accept\\|entry\\)\\>"
  316.   "Regexp for the start of a subprogram.")
  317.  
  318.  
  319. ;;;-------------
  320. ;;;  functions
  321. ;;;-------------
  322.  
  323. (defun ada-xemacs ()
  324.   (or (string-match "Lucid"  emacs-version)
  325.       (string-match "XEmacs" emacs-version)))
  326.  
  327. (defun ada-create-syntax-table ()
  328.   "Create the syntax table for ada-mode."
  329.   ;; There are two different syntax-tables.  The standard one declares
  330.   ;; `_' a symbol constituent, in the second one, it is a word
  331.   ;; constituent.  For some search and replacing routines we
  332.   ;; temporarily switch between the two.
  333.   (setq ada-mode-syntax-table (make-syntax-table))
  334.   (set-syntax-table  ada-mode-syntax-table)
  335.  
  336.   ;; define string brackets (% is alternative string bracket)
  337.   (modify-syntax-entry ?%  "\"" ada-mode-syntax-table)
  338.   (modify-syntax-entry ?\" "\"" ada-mode-syntax-table)
  339.  
  340.   (modify-syntax-entry ?\#  "$" ada-mode-syntax-table)
  341.  
  342.   (modify-syntax-entry ?:  "." ada-mode-syntax-table)
  343.   (modify-syntax-entry ?\; "." ada-mode-syntax-table)
  344.   (modify-syntax-entry ?&  "." ada-mode-syntax-table)
  345.   (modify-syntax-entry ?\|  "." ada-mode-syntax-table)
  346.   (modify-syntax-entry ?+  "." ada-mode-syntax-table)
  347.   (modify-syntax-entry ?*  "." ada-mode-syntax-table)
  348.   (modify-syntax-entry ?/  "." ada-mode-syntax-table)
  349.   (modify-syntax-entry ?=  "." ada-mode-syntax-table)
  350.   (modify-syntax-entry ?<  "." ada-mode-syntax-table)
  351.   (modify-syntax-entry ?>  "." ada-mode-syntax-table)
  352.   (modify-syntax-entry ?$ "." ada-mode-syntax-table)
  353.   (modify-syntax-entry ?\[ "." ada-mode-syntax-table)
  354.   (modify-syntax-entry ?\] "." ada-mode-syntax-table)
  355.   (modify-syntax-entry ?\{ "." ada-mode-syntax-table)
  356.   (modify-syntax-entry ?\} "." ada-mode-syntax-table)
  357.   (modify-syntax-entry ?. "." ada-mode-syntax-table)
  358.   (modify-syntax-entry ?\\ "." ada-mode-syntax-table)
  359.   (modify-syntax-entry ?\' "." ada-mode-syntax-table)
  360.  
  361.   ;; a single hyphen is punctuation, but a double hyphen starts a comment
  362.   (modify-syntax-entry ?-  ". 12" ada-mode-syntax-table)
  363.  
  364.   ;; and \f and \n end a comment
  365.   (modify-syntax-entry ?\f  ">   " ada-mode-syntax-table)
  366.   (modify-syntax-entry ?\n  ">   " ada-mode-syntax-table)
  367.  
  368.   ;; define what belongs in ada symbols
  369.   (modify-syntax-entry ?_ "_" ada-mode-syntax-table)
  370.  
  371.   ;; define parentheses to match
  372.   (modify-syntax-entry ?\( "()" ada-mode-syntax-table)
  373.   (modify-syntax-entry ?\) ")(" ada-mode-syntax-table)
  374.  
  375.   (setq ada-mode-symbol-syntax-table (copy-syntax-table ada-mode-syntax-table))
  376.   (modify-syntax-entry ?_ "w" ada-mode-symbol-syntax-table)
  377.   )
  378.  
  379.  
  380. ;;;###autoload
  381. (defun ada-mode ()
  382.   "Ada Mode is the major mode for editing Ada code.
  383.  
  384. Bindings are as follows: (Note: 'LFD' is control-j.)
  385.  
  386.  Indent line                                          '\\[ada-tab]'
  387.  Indent line, insert newline and indent the new line. '\\[newline-and-indent]'
  388.  
  389.  Re-format the parameter-list point is in             '\\[ada-format-paramlist]'
  390.  Indent all lines in region                           '\\[ada-indent-region]'
  391.  Call external pretty printer program                 '\\[ada-call-pretty-printer]'
  392.  
  393.  Adjust case of identifiers and keywords in region    '\\[ada-adjust-case-region]'
  394.  Adjust case of identifiers and keywords in buffer    '\\[ada-adjust-case-buffer]'
  395.  
  396.  Call EXTERNAL pretty printer (if you have one)       '\\[ada-call-pretty-printer]'
  397.  
  398.  Fill comment paragraph                               '\\[ada-fill-comment-paragraph]'
  399.  Fill comment paragraph and justify each line         '\\[ada-fill-comment-paragraph-justify]'
  400.  Fill comment paragraph, justify and append postfix   '\\[ada-fill-comment-paragraph-postfix]'
  401.  
  402.  Next func/proc/task '\\[ada-next-procedure]'    Previous func/proc/task '\\[ada-previous-procedure]'
  403.  Next package        '\\[ada-next-package]'  Previous package        '\\[ada-previous-package]'
  404.  
  405.  Goto matching start of current 'end ...;'            '\\[ada-move-to-start]'
  406.  Goto end of current block                            '\\[ada-move-to-end]'
  407.  
  408. Comments are handled using standard GNU Emacs conventions, including:
  409.  Start a comment                                      '\\[indent-for-comment]'
  410.  Comment region                                       '\\[comment-region]'
  411.  Uncomment region                                     '\\[ada-uncomment-region]'
  412.  Continue comment on next line                        '\\[indent-new-comment-line]'
  413.  
  414. If you use imenu.el:
  415.  Display index-menu of functions & procedures         '\\[imenu]'
  416.  
  417. If you use find-file.el:
  418.  Switch to other file (Body <-> Spec)                 '\\[ff-find-other-file]'
  419.                                                    or '\\[ff-mouse-find-other-file]
  420.  Switch to other file in other window                 '\\[ada-ff-other-window]'
  421.                                                    or '\\[ff-mouse-find-other-file-other-window]
  422.  If you use this function in a spec and no body is available, it gets created
  423.  with body stubs.
  424.  
  425. If you use ada-xref.el:
  426.  Goto declaration:          '\\[ada-point-and-xref]' on the identifier
  427.                          or '\\[ada-goto-declaration]' with point on the identifier
  428.  Complete identifier:       '\\[ada-complete-identifier]'
  429.  Execute Gnatf:             '\\[ada-gnatf-current]'"
  430.  
  431.   (interactive)
  432.   (kill-all-local-variables)
  433.  
  434.   (make-local-variable 'require-final-newline)
  435.   (setq require-final-newline t)
  436.  
  437.   (make-local-variable 'comment-start)
  438.   (setq comment-start "-- ")
  439.  
  440.   ;; comment end must be set because it may hold a wrong value if
  441.   ;; this buffer had been in another mode before. RE
  442.   (make-local-variable 'comment-end)
  443.   (setq comment-end "")
  444.  
  445.   (make-local-variable 'comment-start-skip) ;; used by autofill
  446.   (setq comment-start-skip "--+[ \t]*")
  447.  
  448.   (make-local-variable 'indent-line-function)
  449.   (setq indent-line-function 'ada-indent-current-function)
  450.  
  451.   (make-local-variable 'fill-column)
  452.   (setq fill-column 75)
  453.  
  454.   (make-local-variable 'comment-column)
  455.   (setq comment-column 40)
  456.  
  457.   (make-local-variable 'parse-sexp-ignore-comments)
  458.   (setq parse-sexp-ignore-comments t)
  459.  
  460.   (make-local-variable 'case-fold-search)
  461.   (setq case-fold-search t)
  462.  
  463.   (make-local-variable 'fill-paragraph-function)
  464.   (setq fill-paragraph-function 'ada-fill-comment-paragraph)
  465.  
  466.   (make-local-variable 'font-lock-defaults)
  467.   (setq font-lock-defaults '(ada-font-lock-keywords nil t ((?\_ . "w"))))
  468.  
  469.   (setq major-mode 'ada-mode)
  470.   (setq mode-name "Ada")
  471.  
  472.   (setq blink-matching-paren t)
  473.  
  474.   (use-local-map ada-mode-map)
  475.  
  476.   (if ada-mode-syntax-table
  477.       (set-syntax-table ada-mode-syntax-table)
  478.     (ada-create-syntax-table))
  479.  
  480.   (if ada-clean-buffer-before-saving
  481.       (progn
  482.     ;; remove all spaces at the end of lines in the whole buffer.
  483.     (add-hook 'local-write-file-hooks 'ada-remove-trailing-spaces)
  484.     ;; convert all tabs to the correct number of spaces.
  485.     (add-hook 'local-write-file-hooks 'ada-untabify-buffer)))
  486.  
  487.  
  488.   ;; add menu 'Ada' to the menu bar
  489.   (ada-add-ada-menu)
  490.  
  491.   (run-hooks 'ada-mode-hook)
  492.  
  493.   ;; the following has to be done after running the ada-mode-hook
  494.   ;; because users might want to set the values of these variable
  495.   ;; inside the hook (MH)
  496.  
  497.   (cond ((eq ada-language-version 'ada83)
  498.          (setq ada-keywords ada-83-keywords))
  499.         ((eq ada-language-version 'ada95)
  500.          (setq ada-keywords ada-95-keywords)))
  501.  
  502.   (if ada-auto-case
  503.       (ada-activate-keys-for-case)))
  504.  
  505.  
  506. ;;;--------------------------
  507. ;;;  Fill Comment Paragraph
  508. ;;;--------------------------
  509.  
  510. (defun ada-fill-comment-paragraph-justify ()
  511.   "Fills current comment paragraph and justifies each line as well."
  512.   (interactive)
  513.   (ada-fill-comment-paragraph t))
  514.  
  515.  
  516. (defun ada-fill-comment-paragraph-postfix ()
  517.   "Fills current comment paragraph and justifies each line as well.
  518. Prompts for a postfix to be appended to each line."
  519.   (interactive)
  520.   (ada-fill-comment-paragraph t t))
  521.  
  522.  
  523. (defun ada-fill-comment-paragraph (&optional justify postfix)
  524.   "Fills the current comment paragraph.
  525. If JUSTIFY is non-nil, each line is justified as well.
  526. If POSTFIX and JUSTIFY are  non-nil, ada-fill-comment-postfix is appended
  527. to each filled and justified line.
  528. If ada-indent-comment-as code is non-nil, the paragraph is idented."
  529.   (interactive "P")
  530.   (let ((opos (point-marker))
  531.         (begin nil)
  532.         (end nil)
  533.         (end-2 nil)
  534.         (indent nil)
  535.         (ada-fill-comment-old-postfix "")
  536.         (fill-prefix nil))
  537.  
  538.     ;; check if inside comment
  539.     (if (not (ada-in-comment-p))
  540.         (error "not inside comment"))
  541.  
  542.     ;; prompt for postfix if wanted
  543.     (if (and justify
  544.              postfix)
  545.         (setq ada-fill-comment-postfix
  546.               (read-from-minibuffer "enter new postfix string: "
  547.                                     ada-fill-comment-postfix)))
  548.  
  549.     ;; prompt for old postfix to remove if necessary
  550.     (if (and justify
  551.              postfix)
  552.         (setq ada-fill-comment-old-postfix
  553.               (read-from-minibuffer "enter already existing postfix string: "
  554.                                     ada-fill-comment-postfix)))
  555.  
  556.     ;;
  557.     ;; find limits of paragraph
  558.     ;;
  559.     (message "filling comment paragraph ...")
  560.     (save-excursion
  561.       (back-to-indentation)
  562.       ;; find end of paragraph
  563.       (while (and (looking-at "--.*$")
  564.                   (not (looking-at "--[ \t]*$")))
  565.         (forward-line 1)
  566.         (back-to-indentation))
  567.       (beginning-of-line)
  568.       (setq end (point-marker))
  569.       (goto-char opos)
  570.       ;; find begin of paragraph
  571.       (back-to-indentation)
  572.       (while (and (looking-at "--.*$")
  573.                   (not (looking-at "--[ \t]*$")))
  574.         (forward-line -1)
  575.         (back-to-indentation))
  576.       (forward-line 1)
  577.       ;; get indentation to calculate width for filling
  578.       (ada-indent-current)
  579.       (back-to-indentation)
  580.       (setq indent (current-column))
  581.       (setq begin (point-marker)))
  582.  
  583.     ;; delete old postfix if necessary
  584.     (if (and justify
  585.              postfix)
  586.         (save-excursion
  587.           (goto-char begin)
  588.           (while (re-search-forward (concat ada-fill-comment-old-postfix
  589.                                             "\n")
  590.                                     end t)
  591.             (replace-match "\n"))))
  592.  
  593.     ;; delete leading whitespace and uncomment
  594.     (save-excursion
  595.       (goto-char begin)
  596.       (beginning-of-line)
  597.       (while (re-search-forward "^[ \t]*--[ \t]*" end t)
  598.         (replace-match "")))
  599.  
  600.     ;; calculate fill width
  601.     (setq fill-column (- fill-column indent
  602.                          (length ada-fill-comment-prefix)
  603.                          (if postfix
  604.                              (length ada-fill-comment-postfix)
  605.                            0)))
  606.     ;; fill paragraph
  607.     (fill-region begin (1- end) justify)
  608.     (setq fill-column (+ fill-column indent
  609.                          (length ada-fill-comment-prefix)
  610.                          (if postfix
  611.                              (length ada-fill-comment-postfix)
  612.                            0)))
  613.    ;; find end of second last line
  614.     (save-excursion
  615.       (goto-char end)
  616.       (forward-line -2)
  617.       (end-of-line)
  618.       (setq end-2 (point-marker)))
  619.  
  620.     ;; re-comment and re-indent region
  621.     (save-excursion
  622.       (goto-char begin)
  623.       (indent-to indent)
  624.       (insert ada-fill-comment-prefix)
  625.       (while (re-search-forward "\n" (1- end-2) t)
  626.         (replace-match (concat "\n" ada-fill-comment-prefix))
  627.         (beginning-of-line)
  628.         (indent-to indent)))
  629.  
  630.     ;; append postfix if wanted
  631.     (if (and justify
  632.              postfix
  633.              ada-fill-comment-postfix)
  634.         (progn
  635.           ;; append postfix up to there
  636.           (save-excursion
  637.             (goto-char begin)
  638.             (while (re-search-forward "\n" (1- end-2) t)
  639.               (replace-match (concat ada-fill-comment-postfix "\n")))
  640.  
  641.             ;; fill last line and append postfix
  642.             (end-of-line)
  643.             (insert-char ?
  644.                          (- fill-column
  645.                             (current-column)
  646.                             (length ada-fill-comment-postfix)))
  647.             (insert ada-fill-comment-postfix))))
  648.  
  649.     ;; delete the extra line that gets inserted somehow(??)
  650.     (save-excursion
  651.       (goto-char (1- end))
  652.       (end-of-line)
  653.       (delete-char 1))
  654.  
  655.      (message "filling comment paragraph ... done")
  656.     (goto-char opos))
  657.   t)
  658.  
  659.  
  660. ;;;--------------------------------;;;
  661. ;;;  Call External Pretty Printer  ;;;
  662. ;;;--------------------------------;;;
  663.  
  664. (defun ada-call-pretty-printer ()
  665.   "Calls the external Pretty Printer.
  666. The name is specified in ada-external-pretty-print-program.  Saves the
  667. current buffer in a directory specified by ada-tmp-directory,
  668. starts the Pretty Printer as external process on that file and then
  669. reloads the beautyfied program in the buffer and cleans up
  670. ada-tmp-directory."
  671.   (interactive)
  672.   (let ((filename-with-path buffer-file-name)
  673.         (curbuf (current-buffer))
  674.         (orgpos (point))
  675.         (mesgbuf nil) ;; for byte-compiling
  676.         (file-path (file-name-directory buffer-file-name))
  677.         (filename-without-path (file-name-nondirectory buffer-file-name))
  678.         (tmp-file-with-directory
  679.          (concat ada-tmp-directory
  680.                  (file-name-nondirectory buffer-file-name))))
  681.     ;;
  682.     ;; save buffer in temporary file
  683.     ;;
  684.     (message "saving current buffer to temporary file ...")
  685.     (write-file tmp-file-with-directory)
  686.     (auto-save-mode nil)
  687.     (message "saving current buffer to temporary file ... done")
  688.     ;;
  689.     ;; call external pretty printer program
  690.     ;;
  691.  
  692.     (message "running external pretty printer ...")
  693.     ;; create a temporary buffer for messages of pretty printer
  694.     (setq mesgbuf (get-buffer-create "Pretty Printer Messages"))
  695.     ;; execute pretty printer on temporary file
  696.     (call-process ada-external-pretty-print-program
  697.                   nil mesgbuf t
  698.                   tmp-file-with-directory)
  699.     ;; display messages if there are some
  700.     (if (buffer-modified-p mesgbuf)
  701.         ;; show the message buffer
  702.         (display-buffer mesgbuf t)
  703.       ;; kill the message buffer
  704.       (kill-buffer mesgbuf))
  705.     (message "running external pretty printer ... done")
  706.     ;;
  707.     ;; kill current buffer and load pretty printer output
  708.     ;; or restore old buffer
  709.     ;;
  710.     (if (y-or-n-p
  711.          "Really replace current buffer with pretty printer output ? ")
  712.         (progn
  713.           (set-buffer-modified-p nil)
  714.           (kill-buffer curbuf)
  715.           (find-file tmp-file-with-directory))
  716.       (message "old buffer contents restored"))
  717.     ;;
  718.     ;; delete temporary file and restore information of current buffer
  719.     ;;
  720.     (delete-file tmp-file-with-directory)
  721.     (set-visited-file-name filename-with-path)
  722.     (auto-save-mode t)
  723.     (goto-char orgpos)))
  724.  
  725.  
  726. ;;;---------------
  727. ;;;  auto-casing
  728. ;;;---------------
  729.  
  730. ;; from Philippe Waroquiers <philippe@cfmu.eurocontrol.be>
  731. ;; modifiedby RE and MH
  732.  
  733. (defun ada-after-keyword-p ()
  734.   ;; returns t if cursor is after a keyword.
  735.   (save-excursion
  736.     (forward-word -1)
  737.     (and (save-excursion
  738.            (or
  739.             (= (point) (point-min))
  740.             (backward-char 1))
  741.            (not (looking-at "_")))     ; (MH)
  742.          (looking-at (concat ada-keywords "[^_]")))))
  743.  
  744. (defun ada-after-char-p ()
  745.   ;; returns t if after ada character "'". This is interpreted as being
  746.   ;; in a character constant.
  747.   (save-excursion
  748.     (if (> (point) 2)
  749.         (progn
  750.           (forward-char -2)
  751.           (looking-at "'"))
  752.       nil)))
  753.  
  754.  
  755. (defun ada-adjust-case (&optional force-identifier)
  756.   "Adjust the case of the word before the just-typed character,
  757. according to ada-case-keyword and ada-case-identifier
  758. If FORCE-IDENTIFIER is non-nil then also adjust keyword as
  759. identifier." ; (MH)
  760.   (forward-char -1)
  761.   (if (and (> (point) 1) (not (or (ada-in-string-p)
  762.                                   (ada-in-comment-p)
  763.                                   (ada-after-char-p))))
  764.       (if (eq (char-syntax (char-after (1- (point)))) ?w)
  765.       (if (save-excursion
  766.         (forward-word -1)
  767.         (or (= (point) (point-min))
  768.             (backward-char 1))
  769.         (looking-at "'"))
  770.           (funcall ada-case-attribute -1)
  771.         (if (and
  772.          (not force-identifier) ; (MH)
  773.          (ada-after-keyword-p))
  774.         (funcall ada-case-keyword -1)
  775.           (funcall ada-case-identifier -1)))))
  776.   (forward-char 1))
  777.  
  778.  
  779. (defun ada-adjust-case-interactive (arg)
  780.   (interactive "P")
  781.   (let ((lastk last-command-char))
  782.     (cond ((or (eq lastk ?\n)
  783.                (eq lastk ?\r))
  784.            ;; horrible kludge
  785.            (insert " ")
  786.            (ada-adjust-case)
  787.            ;; horrible dekludge
  788.            (delete-backward-char 1)
  789.            ;; some special keys and their bindings
  790.            (cond
  791.             ((eq lastk ?\n)
  792.              (funcall ada-lfd-binding))
  793.             ((eq lastk ?\r)
  794.              (funcall ada-ret-binding))))
  795.           ((eq lastk ?\C-i) (ada-tab))
  796.           ((self-insert-command (prefix-numeric-value arg))))
  797.     ;; if there is a keyword in front of the underscore
  798.     ;; then it should be part of an identifier (MH)
  799.     (if (eq lastk ?_)
  800.         (ada-adjust-case t)
  801.       (ada-adjust-case))))
  802.  
  803.  
  804. (defun ada-activate-keys-for-case ()
  805.   ;; save original keybindings to allow swapping ret/lfd
  806.   ;; when casing is activated
  807.   ;; the 'or ...' is there to be sure that the value will not
  808.   ;; be changed again when ada-mode is called more than once (MH)
  809.   (or ada-ret-binding
  810.       (setq ada-ret-binding (key-binding "\C-M")))
  811.   (or ada-lfd-binding
  812.       (setq ada-lfd-binding (key-binding "\C-j")))
  813.   ;; call case modifying function after certain keys.
  814.   (mapcar (function (lambda(key) (define-key
  815.                                    ada-mode-map
  816.                                    (char-to-string key)
  817.                                    'ada-adjust-case-interactive)))
  818.           '( ?` ?~ ?! ?@ ?# ?$ ?% ?^ ?& ?* ?( ?)  ?- ?= ?+ ?[ ?{ ?] ?}
  819.                 ?_ ?\\ ?| ?\; ?: ?' ?\" ?< ?, ?. ?> ?? ?/ ?\n 32 ?\r )))
  820. ;; deleted ?\t from above list
  821.  
  822. ;;
  823. ;; added by MH
  824. ;;
  825. (defun ada-loose-case-word (&optional arg)
  826.   "Capitalizes the first and the letters following _
  827. ARG is ignored, it's there to fit the standard casing functions' style."
  828.   (let ((pos (point))
  829.         (first t))
  830.     (skip-chars-backward "a-zA-Z0-9_")
  831.     (while (or first
  832.                (search-forward "_" pos t))
  833.       (and first
  834.            (setq first nil))
  835.       (insert-char (upcase (following-char)) 1)
  836.       (delete-char 1))
  837.     (goto-char pos)))
  838.  
  839.  
  840. ;;
  841. ;; added by MH
  842. ;;
  843. (defun ada-adjust-case-region (from to)
  844.   "Adjusts the case of all identifiers and keywords in the region.
  845. ATTENTION: This function might take very long for big regions !"
  846.   (interactive "*r")
  847.   (let ((begin nil)
  848.         (end nil)
  849.         (keywordp nil)
  850.         (reldiff nil))
  851.     (unwind-protect
  852.     (save-excursion
  853.       (set-syntax-table ada-mode-symbol-syntax-table)
  854.       (goto-char to)
  855.       ;;
  856.       ;; loop: look for all identifiers and keywords
  857.       ;;
  858.       (while (re-search-backward
  859.           "[^a-zA-Z0-9_]\\([a-zA-Z0-9_]+\\)[^a-zA-Z0-9_]"
  860.           from
  861.           t)
  862.         ;;
  863.         ;; print status message
  864.         ;;
  865.         (setq reldiff (- (point) from))
  866.         (message (format "adjusting case ... %5d characters left"
  867.                  (- (point) from)))
  868.         (forward-char 1)
  869.         (or
  870.          ;; do nothing if it is a string or comment
  871.          (ada-in-string-or-comment-p)
  872.          (progn
  873.            ;;
  874.            ;; get the identifier or keyword
  875.            ;;
  876.            (setq begin (point))
  877.            (setq keywordp (looking-at (concat ada-keywords "[^_]")))
  878.            (skip-chars-forward "a-zA-Z0-9_")
  879.            ;;
  880.            ;; casing according to user-option
  881.            ;;
  882.            (if keywordp
  883.            (funcall ada-case-keyword -1)
  884.          (funcall ada-case-identifier -1))
  885.            (goto-char begin))))
  886.       (message "adjusting case ... done"))
  887.       (set-syntax-table ada-mode-syntax-table))))
  888.  
  889.  
  890. ;;
  891. ;; added by MH
  892. ;;
  893. (defun ada-adjust-case-buffer ()
  894.   "Adjusts the case of all identifiers and keywords in the whole buffer.
  895. ATTENTION: This function might take very long for big buffers !"
  896.   (interactive "*")
  897.   (ada-adjust-case-region (point-min) (point-max)))
  898.  
  899.  
  900. ;;;------------------------;;;
  901. ;;; Format Parameter Lists ;;;
  902. ;;;------------------------;;;
  903.  
  904. (defun ada-format-paramlist ()
  905.   "Re-formats a parameter-list.
  906. ATTENTION:  1) Comments inside the list are killed !
  907.             2) If the syntax is not correct (especially, if there are
  908.                semicolons missing), it can get totally confused !
  909. In such a case, use 'undo', correct the syntax and try again."
  910.  
  911.   (interactive)
  912.   (let ((begin nil)
  913.         (end nil)
  914.         (delend nil)
  915.         (paramlist nil))
  916.     (unwind-protect
  917.     (progn 
  918.       (set-syntax-table ada-mode-symbol-syntax-table)
  919.  
  920.       ;; check if really inside parameter list
  921.       (or (ada-in-paramlist-p)
  922.           (error "not in parameter list"))
  923.       ;;
  924.       ;; find start of current parameter-list
  925.       ;;
  926.       (ada-search-ignore-string-comment
  927.        (concat "\\<\\("
  928.            "procedure\\|function\\|body\\|package\\|task\\|entry\\|accept"
  929.            "\\)\\>") t nil)
  930.       (ada-search-ignore-string-comment "(" nil nil t)
  931.       (backward-char 1)
  932.       (setq begin (point))
  933.  
  934.       ;;
  935.       ;; find end of parameter-list
  936.       ;;
  937.       (forward-sexp 1)
  938.       (setq delend (point))
  939.       (delete-char -1)
  940.  
  941.       ;;
  942.       ;; find end of last parameter-declaration
  943.       ;;
  944.       (ada-search-ignore-string-comment "[^ \t\n]" t nil t)
  945.       (forward-char 1)
  946.       (setq end (point))
  947.  
  948.       ;;
  949.       ;; build a list of all elements of the parameter-list
  950.       ;;
  951.       (setq paramlist (ada-scan-paramlist (1+ begin) end))
  952.  
  953.       ;;
  954.       ;; delete the original parameter-list
  955.       ;;
  956.       (delete-region begin (1- delend))
  957.  
  958.       ;;
  959.       ;; insert the new parameter-list
  960.       ;;
  961.       (goto-char begin)
  962.       (ada-insert-paramlist paramlist))
  963.  
  964.       ;;
  965.       ;; restore syntax-table
  966.       ;;
  967.       (set-syntax-table ada-mode-syntax-table)
  968.       )))
  969.  
  970.  
  971. (defun ada-scan-paramlist (begin end)
  972.   ;; Scans a parameter-list  between BEGIN and END and returns a list
  973.   ;; of its contents.
  974.   ;; The list has the following format:
  975.   ;;
  976.   ;;   Name of Param  in? out? accept?  Name of Type   Default-Exp or nil
  977.   ;;
  978.   ;; ( ('Name_Param_1' t   nil    t      Type_Param_1   ':= expression')
  979.   ;;   ('Name_Param_2' nil nil    t      Type_Param_2    nil) )
  980.  
  981.   (let ((paramlist (list))
  982.         (param (list))
  983.         (notend t)
  984.         (apos nil)
  985.         (epos nil)
  986.         (semipos nil)
  987.         (match-cons nil))
  988.  
  989.     (goto-char begin)
  990.     ;;
  991.     ;; loop until end of last parameter
  992.     ;;
  993.     (while notend
  994.  
  995.       ;;
  996.       ;; find first character of parameter-declaration
  997.       ;;
  998.       (ada-goto-next-non-ws)
  999.       (setq apos (point))
  1000.  
  1001.       ;;
  1002.       ;; find last character of parameter-declaration
  1003.       ;;
  1004.       (if (setq match-cons
  1005.                 (ada-search-ignore-string-comment "[ \t\n]*;" nil end t))
  1006.           (progn
  1007.             (setq epos (car match-cons))
  1008.             (setq semipos (cdr match-cons)))
  1009.         (setq epos end))
  1010.  
  1011.       ;;
  1012.       ;; read name(s) of parameter(s)
  1013.       ;;
  1014.       (goto-char apos)
  1015.       (looking-at "\\([a-zA-Z0-9_, \t\n]*[a-zA-Z0-9_]\\)[ \t\n]*:[^=]")
  1016.  
  1017.       (setq param (list (buffer-substring (match-beginning 1)
  1018.                                           (match-end 1))))
  1019.       (ada-search-ignore-string-comment ":" nil epos t)
  1020.  
  1021.       ;;
  1022.       ;; look for 'in'
  1023.       ;;
  1024.       (setq apos (point))
  1025.       (setq param
  1026.             (append param
  1027.                     (list
  1028.                      (consp
  1029.                       (ada-search-ignore-string-comment "\\<in\\>"
  1030.                                                         nil
  1031.                                                         epos
  1032.                                                         t)))))
  1033.  
  1034.       ;;
  1035.       ;; look for 'out'
  1036.       ;;
  1037.       (goto-char apos)
  1038.       (setq param
  1039.             (append param
  1040.                     (list
  1041.                      (consp
  1042.                       (ada-search-ignore-string-comment "\\<out\\>"
  1043.                                                         nil
  1044.                                                         epos
  1045.                                                         t)))))
  1046.  
  1047.       ;;
  1048.       ;; look for 'accept'
  1049.       ;;
  1050.       (goto-char apos)
  1051.       (setq param
  1052.             (append param
  1053.                     (list
  1054.                      (consp
  1055.                       (ada-search-ignore-string-comment "\\<accept\\>"
  1056.                                                         nil
  1057.                                                         epos
  1058.                                                         t)))))
  1059.  
  1060.       ;;
  1061.       ;; skip 'in'/'out'/'accept'
  1062.       ;;
  1063.       (goto-char apos)
  1064.       (ada-goto-next-non-ws)
  1065.       (while (looking-at "\\<\\(in\\|out\\|accept\\)\\>")
  1066.         (forward-word 1)
  1067.         (ada-goto-next-non-ws))
  1068.  
  1069.       ;;
  1070.       ;; read type of parameter
  1071.       ;;
  1072.       (looking-at "\\<[a-zA-Z0-9_\\.]+\\>")
  1073.       (setq param
  1074.             (append param
  1075.                     (list
  1076.                      (buffer-substring (match-beginning 0)
  1077.                                        (match-end 0)))))
  1078.  
  1079.       ;;
  1080.       ;; read default-expression, if there is one
  1081.       ;;
  1082.       (goto-char (setq apos (match-end 0)))
  1083.       (setq param
  1084.             (append param
  1085.                     (list
  1086.                      (if (setq match-cons
  1087.                                (ada-search-ignore-string-comment ":="
  1088.                                                                  nil
  1089.                                                                  epos
  1090.                                                                  t))
  1091.                          (buffer-substring (car match-cons)
  1092.                                            epos)
  1093.                        nil))))
  1094.       ;;
  1095.       ;; add this parameter-declaration to the list
  1096.       ;;
  1097.       (setq paramlist (append paramlist (list param)))
  1098.  
  1099.       ;;
  1100.       ;; check if it was the last parameter
  1101.       ;;
  1102.       (if (eq epos end)
  1103.           (setq notend nil)
  1104.         (goto-char semipos))
  1105.  
  1106.       ) ; end of loop
  1107.  
  1108.     (reverse paramlist)))
  1109.  
  1110.  
  1111. (defun ada-insert-paramlist (paramlist)
  1112.   ;; Inserts a formatted PARAMLIST in the buffer.
  1113.   ;; See doc of ada-scan-paramlist for the format.
  1114.   (let ((i (length paramlist))
  1115.         (parlen 0)
  1116.         (typlen 0)
  1117.         (temp 0)
  1118.         (inp nil)
  1119.         (outp nil)
  1120.         (acceptp nil)
  1121.         (column nil)
  1122.         (orgpoint 0)
  1123.         (firstcol nil))
  1124.  
  1125.     ;;
  1126.     ;; loop until last parameter
  1127.     ;;
  1128.     (while (not (zerop i))
  1129.       (setq i (1- i))
  1130.  
  1131.       ;;
  1132.       ;; get max length of parameter-name
  1133.       ;;
  1134.       (setq parlen
  1135.             (if (<= parlen (setq temp
  1136.                               (length (nth 0 (nth i paramlist)))))
  1137.                 temp
  1138.               parlen))
  1139.  
  1140.       ;;
  1141.       ;; get max length of type-name
  1142.       ;;
  1143.       (setq typlen
  1144.             (if (<= typlen (setq temp
  1145.                               (length (nth 4 (nth i paramlist)))))
  1146.                 temp
  1147.               typlen))
  1148.  
  1149.       ;;
  1150.       ;; is there any 'in' ?
  1151.       ;;
  1152.       (setq inp
  1153.             (or inp
  1154.                 (nth 1 (nth i paramlist))))
  1155.  
  1156.       ;;
  1157.       ;; is there any 'out' ?
  1158.       ;;
  1159.       (setq outp
  1160.             (or outp
  1161.                 (nth 2 (nth i paramlist))))
  1162.  
  1163.       ;;
  1164.       ;; is there any 'accept' ?
  1165.       ;;
  1166.       (setq acceptp
  1167.             (or acceptp
  1168.                 (nth 3 (nth i paramlist))))) ; end of loop
  1169.  
  1170.     ;;
  1171.     ;; does paramlist already start on a separate line ?
  1172.     ;;
  1173.     (if (save-excursion
  1174.           (re-search-backward "^.\\|[^ \t]" nil t)
  1175.           (looking-at "^."))
  1176.         ;; yes => re-indent it
  1177.         (ada-indent-current)
  1178.       ;;
  1179.       ;; no => insert newline and indent it
  1180.       ;;
  1181.       (progn
  1182.         (ada-indent-current)
  1183.         (newline)
  1184.         (delete-horizontal-space)
  1185.         (setq orgpoint (point))
  1186.         (setq column (save-excursion
  1187.                        (funcall (ada-indent-function) orgpoint)))
  1188.         (indent-to column)
  1189.         ))
  1190.  
  1191.     (insert "(")
  1192.  
  1193.     (setq firstcol (current-column))
  1194.     (setq i (length paramlist))
  1195.  
  1196.     ;;
  1197.     ;; loop until last parameter
  1198.     ;;
  1199.     (while (not (zerop i))
  1200.       (setq i (1- i))
  1201.       (setq column firstcol)
  1202.  
  1203.       ;;
  1204.       ;; insert parameter-name, space and colon
  1205.       ;;
  1206.       (insert (nth 0 (nth i paramlist)))
  1207.       (indent-to (+ column parlen 1))
  1208.       (insert ": ")
  1209.       (setq column (current-column))
  1210.  
  1211.       ;;
  1212.       ;; insert 'in' or space
  1213.       ;;
  1214.       (if (nth 1 (nth i paramlist))
  1215.           (insert "in ")
  1216.         (if (and
  1217.              (or inp
  1218.                  acceptp)
  1219.              (not (nth 3 (nth i paramlist))))
  1220.             (insert "   ")))
  1221.  
  1222.       ;;
  1223.       ;; insert 'out' or space
  1224.       ;;
  1225.       (if (nth 2 (nth i paramlist))
  1226.           (insert "out ")
  1227.         (if (and
  1228.              (or outp
  1229.                  acceptp)
  1230.              (not (nth 3 (nth i paramlist))))
  1231.             (insert "    ")))
  1232.  
  1233.       ;;
  1234.       ;; insert 'accept'
  1235.       ;;
  1236.       (if (nth 3 (nth i paramlist))
  1237.           (insert "accept "))
  1238.  
  1239.       (setq column (current-column))
  1240.  
  1241.       ;;
  1242.       ;; insert type-name and, if necessary, space and default-expression
  1243.       ;;
  1244.       (insert (nth 4 (nth i paramlist)))
  1245.       (if (nth 5 (nth i paramlist))
  1246.           (progn
  1247.             (indent-to (+ column typlen 1))
  1248.             (insert (nth 5 (nth i paramlist)))))
  1249.  
  1250.       ;;
  1251.       ;; check if it was the last parameter
  1252.       ;;
  1253.       (if (not (zerop i))
  1254.           ;; no => insert ';' and newline and indent
  1255.           (progn
  1256.             (insert ";")
  1257.             (newline)
  1258.             (indent-to firstcol))
  1259.         ;; yes
  1260.         (insert ")"))
  1261.  
  1262.       ) ; end of loop
  1263.  
  1264.     ;;
  1265.     ;; if anything follows, except semicolon:
  1266.     ;; put it in a new line and indent it
  1267.     ;;
  1268.     (if (not (looking-at "[ \t]*[;\n]"))
  1269.         (ada-indent-newline-indent))
  1270.  
  1271.     ))
  1272.  
  1273.  
  1274. ;;;----------------------------;;;
  1275. ;;; Move To Matching Start/End ;;;
  1276. ;;;----------------------------;;;
  1277.  
  1278. (defun ada-move-to-start ()
  1279.   "Moves point to the matching start of the current end ... around point."
  1280.   (interactive)
  1281.   (let ((pos (point)))
  1282.     (unwind-protect
  1283.     (progn
  1284.       (set-syntax-table ada-mode-symbol-syntax-table)
  1285.  
  1286.       (message "searching for block start ...")
  1287.       (save-excursion
  1288.         ;;
  1289.         ;; do nothing if in string or comment or not on 'end ...;'
  1290.         ;;            or if an error occurs during processing
  1291.         ;;
  1292.         (or
  1293.          (ada-in-string-or-comment-p)
  1294.          (and (progn
  1295.             (or (looking-at "[ \t]*\\<end\\>")
  1296.             (backward-word 1))
  1297.             (or (looking-at "[ \t]*\\<end\\>")
  1298.             (backward-word 1))
  1299.             (or (looking-at "[ \t]*\\<end\\>")
  1300.             (error "not on end ...;")))
  1301.           (ada-goto-matching-start 1)
  1302.           (setq pos (point))
  1303.  
  1304.           ;;
  1305.           ;; on 'begin' => go on, according to user option
  1306.           ;;
  1307.           ada-move-to-declaration
  1308.           (looking-at "\\<begin\\>")
  1309.           (ada-goto-matching-decl-start)
  1310.           (setq pos (point))))
  1311.  
  1312.         ) ; end of save-excursion
  1313.  
  1314.       ;; now really move to the found position
  1315.       (goto-char pos)
  1316.       (message "searching for block start ... done"))
  1317.  
  1318.       ;;
  1319.       ;; restore syntax-table
  1320.       ;;
  1321.       (set-syntax-table ada-mode-syntax-table))))
  1322.  
  1323.  
  1324. (defun ada-move-to-end ()
  1325.   "Moves point to the matching end of the current block around point.
  1326. Moves to 'begin' if in a declarative part."
  1327.   (interactive)
  1328.   (let ((pos (point))
  1329.         (decstart nil)
  1330.         (packdecl nil))
  1331.     (unwind-protect
  1332.     (progn
  1333.       (set-syntax-table ada-mode-symbol-syntax-table)
  1334.  
  1335.       (message "searching for block end ...")
  1336.       (save-excursion
  1337.  
  1338.         (forward-char 1)
  1339.         (cond
  1340.          ;; directly on 'begin'
  1341.          ((save-excursion
  1342.         (ada-goto-previous-word)
  1343.         (looking-at "\\<begin\\>"))
  1344.           (ada-goto-matching-end 1))
  1345.          ;; on first line of defun declaration
  1346.          ((save-excursion
  1347.         (and (ada-goto-stmt-start)
  1348.              (looking-at "\\<function\\>\\|\\<procedure\\>" )))
  1349.           (ada-search-ignore-string-comment "\\<begin\\>"))
  1350.          ;; on first line of task declaration
  1351.          ((save-excursion
  1352.         (and (ada-goto-stmt-start)
  1353.              (looking-at "\\<task\\>" )
  1354.              (forward-word 1)
  1355.              (ada-search-ignore-string-comment "[^ \n\t]")
  1356.              (not (backward-char 1))
  1357.              (looking-at "\\<body\\>")))
  1358.           (ada-search-ignore-string-comment "\\<begin\\>"))
  1359.          ;; accept block start
  1360.          ((save-excursion
  1361.         (and (ada-goto-stmt-start)
  1362.              (looking-at "\\<accept\\>" )))
  1363.           (ada-goto-matching-end 0))
  1364.          ;; package start
  1365.          ((save-excursion
  1366.         (and (ada-goto-matching-decl-start t)
  1367.              (looking-at "\\<package\\>")))
  1368.           (ada-goto-matching-end 1))
  1369.          ;; inside a 'begin' ... 'end' block
  1370.          ((save-excursion
  1371.         (ada-goto-matching-decl-start t))
  1372.           (ada-search-ignore-string-comment "\\<begin\\>"))
  1373.          ;; (hopefully ;-) everything else
  1374.          (t
  1375.           (ada-goto-matching-end 1)))
  1376.         (setq pos (point))
  1377.  
  1378.         ) ; end of save-excursion
  1379.  
  1380.       ;; now really move to the found position
  1381.       (goto-char pos)
  1382.       (message "searching for block end ... done"))
  1383.       
  1384.       ;;
  1385.       ;; restore syntax-table
  1386.       ;;
  1387.       (set-syntax-table ada-mode-syntax-table))))
  1388.  
  1389.  
  1390. ;;;-----------------------------;;;
  1391. ;;;  Functions For Indentation  ;;;
  1392. ;;;-----------------------------;;;
  1393.  
  1394. ;; ---- main functions for indentation
  1395.  
  1396. (defun ada-indent-region (beg end)
  1397.   "Indents the region using ada-indent-current on each line."
  1398.   (interactive "*r")
  1399.   (goto-char beg)
  1400.   (let ((block-done 0)
  1401.     (lines-remaining (count-lines beg end))
  1402.     (msg (format "indenting %4d lines %%4d lines remaining ..."
  1403.              (count-lines beg end)))
  1404.         (endmark (copy-marker end)))
  1405.     ;; catch errors while indenting
  1406.     (condition-case err
  1407.         (while (< (point) endmark)
  1408.           (if (> block-done 9)
  1409.               (progn (message (format msg lines-remaining))
  1410.                      (setq block-done 0)))
  1411.       (if (looking-at "^$") nil
  1412.         (ada-indent-current))
  1413.           (forward-line 1)
  1414.       (setq block-done (1+ block-done))
  1415.       (setq lines-remaining (1- lines-remaining)))
  1416.       ;; show line number where the error occured
  1417.       (error
  1418.        (error (format "line %d: %s"
  1419.                       (1+ (count-lines (point-min) (point)))
  1420.                       err) nil)))
  1421.     (message "indenting ... done")))
  1422.  
  1423.  
  1424. (defun ada-indent-newline-indent ()
  1425.   "Indents the current line, inserts a newline and then indents the new line."
  1426.   (interactive "*")
  1427.   (let ((column)
  1428.         (orgpoint))
  1429.  
  1430.     (ada-indent-current)
  1431.     (newline)
  1432.     (delete-horizontal-space)
  1433.     (setq orgpoint (point))
  1434.  
  1435.     (unwind-protect
  1436.     (progn
  1437.       (set-syntax-table ada-mode-symbol-syntax-table)
  1438.  
  1439.       (setq column (save-excursion
  1440.              (funcall (ada-indent-function) orgpoint))))
  1441.  
  1442.       ;;
  1443.       ;; restore syntax-table
  1444.       ;;
  1445.       (set-syntax-table ada-mode-syntax-table))
  1446.  
  1447.     (indent-to column)
  1448.  
  1449.     ;; The following is needed to ensure that indentation will still be
  1450.     ;; correct if something follows behind point when typing LFD
  1451.     ;; For example: Imagine point to be there (*) when LFD is typed:
  1452.     ;;              while cond loop
  1453.     ;;                 null; *end loop;
  1454.     ;; Result without the following statement would be:
  1455.     ;;              while cond loop
  1456.     ;;                 null;
  1457.     ;;                *end loop;
  1458.     ;; You would then have to type TAB to correct it.
  1459.     ;; If that doesn't bother you, you can comment out the following
  1460.     ;; statement to speed up indentation a LITTLE bit.
  1461.  
  1462.     (if (not (looking-at "[ \t]*$"))
  1463.         (ada-indent-current))
  1464.     ))
  1465.  
  1466.  
  1467. (defun ada-indent-current ()
  1468.   "Indents current line as Ada code.
  1469. This works by two steps:
  1470.  1) It moves point to the end of the previous code-line.
  1471.     Then it calls the function to calculate the indentation for the
  1472.     following line as if a newline would be inserted there.
  1473.     The calculated column # is saved and the old position of point
  1474.     is restored.
  1475.  2) Then another function is called to calculate the indentation for
  1476.     the current line, based on the previously calculated column #."
  1477.  
  1478.   (interactive)
  1479.  
  1480.   (unwind-protect
  1481.       (progn
  1482.     (set-syntax-table ada-mode-symbol-syntax-table)
  1483.  
  1484.     (let ((line-end)
  1485.           (orgpoint (point-marker))
  1486.           (cur-indent)
  1487.           (prev-indent)
  1488.           (prevline t))
  1489.  
  1490.       ;;
  1491.       ;; first step
  1492.       ;;
  1493.       (save-excursion
  1494.         (if (ada-goto-prev-nonblank-line t)
  1495.         ;;
  1496.         ;; we are not in the first accessible line in the buffer
  1497.         ;;
  1498.         (progn
  1499.           ;;(end-of-line)
  1500.           ;;(forward-char 1)
  1501.           ;; we are already at the BOL
  1502.           (forward-line 1)
  1503.           (setq line-end (point))
  1504.           (setq prev-indent
  1505.             (save-excursion
  1506.               (funcall (ada-indent-function) line-end))))
  1507.           (setq prevline nil)))
  1508.  
  1509.       (if prevline
  1510.           ;;
  1511.           ;; we are not in the first accessible line in the buffer
  1512.           ;;
  1513.           (progn
  1514.         ;;
  1515.         ;; second step
  1516.         ;;
  1517.         (back-to-indentation)
  1518.         (setq cur-indent (ada-get-current-indent prev-indent))
  1519.         (delete-horizontal-space)
  1520.         (indent-to cur-indent)
  1521.  
  1522.         ;;
  1523.         ;; restore position of point
  1524.         ;;
  1525.         (goto-char orgpoint)
  1526.         (if (< (current-column) (current-indentation))
  1527.               (back-to-indentation))))))
  1528.  
  1529.     ;;
  1530.     ;; restore syntax-table
  1531.     ;;
  1532.     (set-syntax-table ada-mode-syntax-table)))
  1533.  
  1534.  
  1535. (defun ada-get-current-indent (prev-indent)
  1536.   ;; Returns the column # to indent the current line to.
  1537.   ;; PREV-INDENT is the indentation resulting from the previous lines.
  1538.   (let ((column nil)
  1539.         (pos nil)
  1540.         (match-cons nil))
  1541.  
  1542.     (cond
  1543.      ;;
  1544.      ;; in open parenthesis, but not in parameter-list
  1545.      ;;
  1546.      ((and
  1547.        ada-indent-to-open-paren
  1548.        (not (ada-in-paramlist-p))
  1549.        (setq column (ada-in-open-paren-p)))
  1550.       ;; check if we have something like this  (Table_Component_Type =>
  1551.       ;;                                          Source_File_Record,)
  1552.       (save-excursion
  1553.         (if (and (ada-search-ignore-string-comment "[^ \t]" t nil)
  1554.                  (looking-at "\n")
  1555.                  (ada-search-ignore-string-comment "[^ \t\n]" t nil)
  1556.                  (looking-at ">"))
  1557.             (setq column (+ ada-broken-indent column))))
  1558.       column)
  1559.  
  1560.      ;;
  1561.      ;; end
  1562.      ;;
  1563.      ((looking-at "\\<end\\>")
  1564.       (save-excursion
  1565.         (ada-goto-matching-start 1)
  1566.  
  1567.         ;;
  1568.         ;; found 'loop' => skip back to 'while' or 'for'
  1569.         ;;                 if 'loop' is not on a separate line
  1570.         ;;
  1571.         (if (and
  1572.              (looking-at "\\<loop\\>")
  1573.              (save-excursion
  1574.                (back-to-indentation)
  1575.                (not (looking-at "\\<loop\\>"))))
  1576.             (if (save-excursion
  1577.                   (and
  1578.                    (setq match-cons
  1579.                          (ada-search-ignore-string-comment
  1580.                           ada-loop-start-re t nil))
  1581.                    (not (looking-at "\\<loop\\>"))))
  1582.                 (goto-char (car match-cons))))
  1583.  
  1584.         (current-indentation)))
  1585.      ;;
  1586.      ;; exception
  1587.      ;;
  1588.      ((looking-at "\\<exception\\>")
  1589.       (save-excursion
  1590.         (ada-goto-matching-start 1)
  1591.         (current-indentation)))
  1592.      ;;
  1593.      ;; when
  1594.      ;;
  1595.      ((looking-at "\\<when\\>")
  1596.       (save-excursion
  1597.         (ada-goto-matching-start 1)
  1598.         (+ (current-indentation) ada-when-indent)))
  1599.      ;;
  1600.      ;; else
  1601.      ;;
  1602.      ((looking-at "\\<else\\>")
  1603.       (if (save-excursion
  1604.             (ada-goto-previous-word)
  1605.             (looking-at "\\<or\\>"))
  1606.           prev-indent
  1607.         (save-excursion
  1608.           (ada-goto-matching-start 1 nil t)
  1609.           (current-indentation))))
  1610.      ;;
  1611.      ;; elsif
  1612.      ;;
  1613.      ((looking-at "\\<elsif\\>")
  1614.       (save-excursion
  1615.         (ada-goto-matching-start 1 nil t)
  1616.         (current-indentation)))
  1617.      ;;
  1618.      ;; then
  1619.      ;;
  1620.      ((looking-at "\\<then\\>")
  1621.       (if (save-excursion
  1622.             (ada-goto-previous-word)
  1623.             (looking-at "\\<and\\>"))
  1624.           prev-indent
  1625.         (save-excursion
  1626.           (ada-search-ignore-string-comment "\\<elsif\\>\\|\\<if\\>" t nil)
  1627.           (+ (current-indentation) ada-stmt-end-indent))))
  1628.      ;;
  1629.      ;; loop
  1630.      ;;
  1631.      ((looking-at "\\<loop\\>")
  1632.       (setq pos (point))
  1633.       (save-excursion
  1634.         (goto-char (match-end 0))
  1635.         (ada-goto-stmt-start)
  1636.         (if (looking-at "\\<loop\\>\\|\\<if\\>")
  1637.             prev-indent
  1638.           (progn
  1639.             (if (not (looking-at ada-loop-start-re))
  1640.                 (ada-search-ignore-string-comment ada-loop-start-re
  1641.                                                   nil pos))
  1642.             (if (looking-at "\\<loop\\>")
  1643.                 prev-indent
  1644.               (+ (current-indentation) ada-stmt-end-indent))))))
  1645.      ;;
  1646.      ;; begin
  1647.      ;;
  1648.      ((looking-at "\\<begin\\>")
  1649.       (save-excursion
  1650.         (if (ada-goto-matching-decl-start t)
  1651.             (current-indentation)
  1652.           (progn
  1653.             (message "no matching declaration start")
  1654.             prev-indent))))
  1655.      ;;
  1656.      ;; is
  1657.      ;;
  1658.      ((looking-at "\\<is\\>")
  1659.       (if (and
  1660.            ada-indent-is-separate
  1661.            (save-excursion
  1662.              (goto-char (match-end 0))
  1663.              (ada-goto-next-non-ws (save-excursion
  1664.                                      (end-of-line)
  1665.                                      (point)))
  1666.              (looking-at "\\<abstract\\>\\|\\<separate\\>")))
  1667.           (save-excursion
  1668.             (ada-goto-stmt-start)
  1669.             (+ (current-indentation) ada-indent))
  1670.         (save-excursion
  1671.           (ada-goto-stmt-start)
  1672.           (+ (current-indentation) ada-stmt-end-indent))))
  1673.      ;;
  1674.      ;; record
  1675.      ;;
  1676.      ((looking-at "\\<record\\>")
  1677.       (save-excursion
  1678.         (ada-search-ignore-string-comment
  1679.          "\\<\\(type\\|use\\)\\>" t nil)
  1680.         (if (looking-at "\\<use\\>")
  1681.             (ada-search-ignore-string-comment "\\<for\\>" t nil))
  1682.         (+ (current-indentation) ada-indent-record-rel-type)))
  1683.      ;;
  1684.      ;; or as statement-start
  1685.      ;;
  1686.      ((ada-looking-at-semi-or)
  1687.       (save-excursion
  1688.         (ada-goto-matching-start 1)
  1689.         (current-indentation)))
  1690.      ;;
  1691.      ;; private as statement-start
  1692.      ;;
  1693.      ((ada-looking-at-semi-private)
  1694.       (save-excursion
  1695.         (ada-goto-matching-decl-start)
  1696.         (current-indentation)))
  1697.      ;;
  1698.      ;; new/abstract/separate
  1699.      ;;
  1700.      ((looking-at "\\<\\(new\\|abstract\\|separate\\)\\>")
  1701.       (- prev-indent ada-indent (- ada-broken-indent)))
  1702.      ;;
  1703.      ;; return
  1704.      ;;
  1705.      ((looking-at "\\<return\\>")
  1706.       (save-excursion
  1707.         (forward-sexp -1)
  1708.         (if (and (looking-at "(")
  1709.                  (save-excursion
  1710.                    (backward-sexp 2)
  1711.                    (looking-at "\\<function\\>")))
  1712.             (1+ (current-column))
  1713.           prev-indent)))
  1714.      ;;
  1715.      ;; do
  1716.      ;;
  1717.      ((looking-at "\\<do\\>")
  1718.       (save-excursion
  1719.         (ada-goto-stmt-start)
  1720.         (+ (current-indentation) ada-stmt-end-indent)))
  1721.      ;;
  1722.      ;; package/function/procedure
  1723.      ;;
  1724.      ((and (looking-at "\\<\\(package\\|function\\|procedure\\)\\>")
  1725.            (save-excursion
  1726.              (forward-char 1)
  1727.              (ada-goto-stmt-start)
  1728.              (looking-at "\\<\\(package\\|function\\|procedure\\)\\>")))
  1729.       (save-excursion
  1730.         ;; look for 'generic'
  1731.         (if (and (ada-goto-matching-decl-start t)
  1732.                  (looking-at "generic"))
  1733.             (current-column)
  1734.           prev-indent)))
  1735.      ;;
  1736.      ;; label
  1737.      ;;
  1738.      ((looking-at "\\<[a-zA-Z0-9_]+[ \t\n]*:[^=]")
  1739.       (if (ada-in-decl-p)
  1740.           prev-indent
  1741.         (+ prev-indent ada-label-indent)))
  1742.      ;;
  1743.      ;; identifier and other noindent-statements
  1744.      ;;
  1745.      ((looking-at "\\<[a-zA-Z0-9_]+[ \t\n]*")
  1746.       prev-indent)
  1747.      ;;
  1748.      ;; beginning of a parameter list
  1749.      ;;
  1750.      ((looking-at "(")
  1751.       prev-indent)
  1752.      ;;
  1753.      ;; end of a parameter list
  1754.      ;;
  1755.      ((looking-at ")")
  1756.       (save-excursion
  1757.         (forward-char 1)
  1758.         (backward-sexp 1)
  1759.         (current-column)))
  1760.      ;;
  1761.      ;; comment
  1762.      ;;
  1763.      ((looking-at "--")
  1764.       (if ada-indent-comment-as-code
  1765.           prev-indent
  1766.         (current-indentation)))
  1767.      ;;
  1768.      ;; unknown syntax - maybe this should signal an error ?
  1769.      ;;
  1770.      (t
  1771.       prev-indent))))
  1772.  
  1773.  
  1774. (defun ada-indent-function (&optional nomove)
  1775.   ;; Returns the function to calculate the indentation for the current
  1776.   ;; line according to the previous statement, ignoring the contents
  1777.   ;; of the current line after point.  Moves point to the beginning of
  1778.   ;; the current statement, if NOMOVE is nil.
  1779.  
  1780.   (let ((orgpoint (point))
  1781.         (func nil)
  1782.         (stmt-start nil))
  1783.     ;;
  1784.     ;; inside a parameter-list
  1785.     ;;
  1786.     (if (ada-in-paramlist-p)
  1787.         (setq func 'ada-get-indent-paramlist)
  1788.       (progn
  1789.         ;;
  1790.         ;; move to beginning of current statement
  1791.         ;;
  1792.         (if (not nomove)
  1793.             (setq stmt-start (ada-goto-stmt-start)))
  1794.         ;;
  1795.         ;; no beginning found => don't change indentation
  1796.         ;;
  1797.         (if (and
  1798.              (eq orgpoint (point))
  1799.              (not nomove))
  1800.               (setq func 'ada-get-indent-nochange)
  1801.  
  1802.           (cond
  1803.            ;;
  1804.            ((and
  1805.              ada-indent-to-open-paren
  1806.              (ada-in-open-paren-p))
  1807.             (setq func 'ada-get-indent-open-paren))
  1808.            ;;
  1809.            ((looking-at "\\<end\\>")
  1810.             (setq func 'ada-get-indent-end))
  1811.            ;;
  1812.            ((looking-at ada-loop-start-re)
  1813.             (setq func 'ada-get-indent-loop))
  1814.            ;;
  1815.            ((looking-at ada-subprog-start-re)
  1816.             (setq func 'ada-get-indent-subprog))
  1817.            ;;
  1818.            ((looking-at "\\<package\\>")
  1819.             (setq func 'ada-get-indent-subprog)) ; maybe it needs a
  1820.                                                  ; special function
  1821.                                                  ; sometimes ?
  1822.            ;;
  1823.            ((looking-at ada-block-start-re)
  1824.             (setq func 'ada-get-indent-block-start))
  1825.            ;;
  1826.            ((looking-at "\\<type\\>")
  1827.             (setq func 'ada-get-indent-type))
  1828.            ;;
  1829.            ((looking-at "\\<\\(els\\)?if\\>")
  1830.             (setq func 'ada-get-indent-if))
  1831.            ;;
  1832.            ((looking-at "\\<case\\>")
  1833.             (setq func 'ada-get-indent-case))
  1834.            ;;
  1835.            ((looking-at "\\<when\\>")
  1836.             (setq func 'ada-get-indent-when))
  1837.            ;;
  1838.            ((looking-at "--")
  1839.             (setq func 'ada-get-indent-comment))
  1840.            ;;
  1841.            ((looking-at "[a-zA-Z0-9_]+[ \t\n]*:[^=]")
  1842.             (setq func 'ada-get-indent-label))
  1843.            ;;
  1844.        ((looking-at "\\<separate\\>")
  1845.         (setq func 'ada-get-indent-nochange))
  1846.            (t
  1847.             (setq func 'ada-get-indent-noindent))))))
  1848.  
  1849.     func))
  1850.  
  1851.  
  1852. ;; ---- functions to return indentation for special cases
  1853.  
  1854. (defun ada-get-indent-open-paren (orgpoint)
  1855.   ;; Returns the indentation (column #) for the new line after ORGPOINT.
  1856.   ;; Assumes point to be behind an open paranthesis not yet closed.
  1857.   (ada-in-open-paren-p))
  1858.  
  1859.  
  1860. (defun ada-get-indent-nochange (orgpoint)
  1861.   ;; Returns the indentation (column #) of the current line.
  1862.   (save-excursion
  1863.     (forward-line -1)
  1864.     (current-indentation)))
  1865.  
  1866.  
  1867. (defun ada-get-indent-paramlist (orgpoint)
  1868.   ;; Returns the indentation (column #) for the new line after ORGPOINT.
  1869.   ;; Assumes point to be inside a parameter-list.
  1870.   (save-excursion
  1871.     (ada-search-ignore-string-comment "[^ \t\n]" t nil t)
  1872.     (cond
  1873.      ;;
  1874.      ;; in front of the first parameter
  1875.      ;;
  1876.      ((looking-at "(")
  1877.       (goto-char (match-end 0))
  1878.       (current-column))
  1879.      ;;
  1880.      ;; in front of another parameter
  1881.      ;;
  1882.      ((looking-at ";")
  1883.       (goto-char (cdr (ada-search-ignore-string-comment "(\\|;" t nil t)))
  1884.       (ada-goto-next-non-ws)
  1885.       (current-column))
  1886.      ;;
  1887.      ;; inside a parameter declaration
  1888.      ;;
  1889.      (t
  1890.       (goto-char (cdr (ada-search-ignore-string-comment "(\\|;" t nil t)))
  1891.       (ada-goto-next-non-ws)
  1892.       (+ (current-column) ada-broken-indent)))))
  1893.  
  1894.  
  1895. (defun ada-get-indent-end (orgpoint)
  1896.   ;; Returns the indentation (column #) for the new line after ORGPOINT.
  1897.   ;; Assumes point to be at the beginning of an end-statement.
  1898.   ;; Therefore it has to find the corresponding start. This can be a little
  1899.   ;; slow, if it has to search through big files with many nested blocks.
  1900.   ;; Signals an error if the corresponding block-start doesn't match.
  1901.   (let ((defun-name nil)
  1902.         (indent nil))
  1903.     ;;
  1904.     ;; is the line already terminated by ';' ?
  1905.     ;;
  1906.     (if (save-excursion
  1907.           (ada-search-ignore-string-comment ";" nil orgpoint))
  1908.         ;;
  1909.         ;; yes, look what's following 'end'
  1910.         ;;
  1911.         (progn
  1912.           (forward-word 1)
  1913.           (ada-goto-next-non-ws)
  1914.           (cond
  1915.            ;;
  1916.            ;; loop/select/if/case/record/select
  1917.            ;;
  1918.            ((looking-at "\\<\\(loop\\|select\\|if\\|case\\|record\\)\\>")
  1919.             (save-excursion
  1920.               (ada-check-matching-start
  1921.                (buffer-substring (match-beginning 0)
  1922.                                  (match-end 0)))
  1923.               (if (looking-at "\\<\\(loop\\|record\\)\\>")
  1924.                   (progn
  1925.                     (forward-word 1)
  1926.                     (ada-goto-stmt-start)))
  1927.               ;; a label ? => skip it
  1928.               (if (looking-at "[a-zA-Z0-9_]+[ \n\t]+:")
  1929.                   (progn
  1930.                     (goto-char (match-end 0))
  1931.                     (ada-goto-next-non-ws)))
  1932.               ;; really looking-at the right thing ?
  1933.               (or (looking-at (concat "\\<\\("
  1934.                                       "loop\\|select\\|if\\|case\\|"
  1935.                                       "record\\|while\\|type\\)\\>"))
  1936.                   (progn
  1937.                     (ada-search-ignore-string-comment
  1938.                      (concat "\\<\\("
  1939.                              "loop\\|select\\|if\\|case\\|"
  1940.                              "record\\|while\\|type\\)\\>")))
  1941.                   (backward-word 1))
  1942.               (current-indentation)))
  1943.            ;;
  1944.            ;; a named block end
  1945.            ;;
  1946.            ((looking-at ada-ident-re)
  1947.             (setq defun-name (buffer-substring (match-beginning 0)
  1948.                                                (match-end 0)))
  1949.             (save-excursion
  1950.               (ada-goto-matching-start 0)
  1951.               (ada-check-defun-name defun-name)
  1952.               (current-indentation)))
  1953.            ;;
  1954.            ;; a block-end without name
  1955.            ;;
  1956.            ((looking-at ";")
  1957.             (save-excursion
  1958.               (ada-goto-matching-start 0)
  1959.               (if (looking-at "\\<begin\\>")
  1960.                   (progn
  1961.                     (setq indent (current-column))
  1962.                     (if (ada-goto-matching-decl-start t)
  1963.                         (current-indentation)
  1964.                       indent)))))
  1965.            ;;
  1966.            ;; anything else - should maybe signal an error ?
  1967.            ;;
  1968.            (t
  1969.             (+ (current-indentation) ada-broken-indent))))
  1970.  
  1971.       (+ (current-indentation) ada-broken-indent))))
  1972.  
  1973.  
  1974. (defun ada-get-indent-case (orgpoint)
  1975.   ;; Returns the indentation (column #) for the new line after ORGPOINT.
  1976.   ;; Assumes point to be at the beginning of an case-statement.
  1977.   (let ((cur-indent (current-indentation))
  1978.         (match-cons nil)
  1979.         (opos (point)))
  1980.     (cond
  1981.      ;;
  1982.      ;; case..is..when..=>
  1983.      ;;
  1984.      ((save-excursion
  1985.        (setq match-cons (ada-search-ignore-string-comment
  1986.                          "[ \t\n]+=>" nil orgpoint)))
  1987.       (save-excursion
  1988.         (goto-char (car match-cons))
  1989.         (if (not (ada-search-ignore-string-comment "\\<when\\>" t opos))
  1990.             (error "missing 'when' between 'case' and '=>'"))
  1991.         (+ (current-indentation) ada-indent)))
  1992.      ;;
  1993.      ;; case..is..when
  1994.      ;;
  1995.      ((save-excursion
  1996.        (setq match-cons (ada-search-ignore-string-comment
  1997.                          "\\<when\\>" nil orgpoint)))
  1998.       (goto-char (cdr match-cons))
  1999.       (+ (current-indentation) ada-broken-indent))
  2000.      ;;
  2001.      ;; case..is
  2002.      ;;
  2003.      ((save-excursion
  2004.        (setq match-cons (ada-search-ignore-string-comment
  2005.                          "\\<is\\>" nil orgpoint)))
  2006.       (+ (current-indentation) ada-when-indent))
  2007.      ;;
  2008.      ;; incomplete case
  2009.      ;;
  2010.      (t
  2011.       (+ (current-indentation) ada-broken-indent)))))
  2012.  
  2013.  
  2014. (defun ada-get-indent-when (orgpoint)
  2015.   ;; Returns the indentation (column #) for the new line after ORGPOINT.
  2016.   ;; Assumes point to be at the beginning of an when-statement.
  2017.   (let ((cur-indent (current-indentation)))
  2018.     (if (ada-search-ignore-string-comment
  2019.          "[ \t\n]+=>" nil orgpoint)
  2020.         (+ cur-indent  ada-indent)
  2021.       (+ cur-indent ada-broken-indent))))
  2022.  
  2023.  
  2024. (defun ada-get-indent-if (orgpoint)
  2025.   ;; Returns the indentation (column #) for the new line after ORGPOINT.
  2026.   ;; Assumes point to be at the beginning of an if-statement.
  2027.   (let ((cur-indent (current-indentation))
  2028.         (match-cons nil))
  2029.     ;;
  2030.     ;; if..then ?
  2031.     ;;
  2032.     (if (ada-search-but-not
  2033.          "\\<then\\>" "\\<and\\>[ \t\n]+\\<then\\>" nil orgpoint)
  2034.  
  2035.         (progn
  2036.           ;;
  2037.           ;; 'then' first in separate line ?
  2038.           ;; => indent according to 'then'
  2039.           ;;
  2040.           (if (save-excursion
  2041.                 (back-to-indentation)
  2042.                 (looking-at "\\<then\\>"))
  2043.               (setq cur-indent (current-indentation)))
  2044.           (forward-word 1)
  2045.           ;;
  2046.           ;; something follows 'then' ?
  2047.           ;;
  2048.           (if (setq match-cons
  2049.                     (ada-search-ignore-string-comment
  2050.                      "[^ \t\n]" nil orgpoint))
  2051.               (progn
  2052.                 (goto-char (car match-cons))
  2053.                 (+ ada-indent
  2054.                    (- cur-indent (current-indentation))
  2055.                    (funcall (ada-indent-function t) orgpoint)))
  2056.  
  2057.             (+ cur-indent ada-indent)))
  2058.  
  2059.       (+ cur-indent ada-broken-indent))))
  2060.  
  2061.  
  2062. (defun ada-get-indent-block-start (orgpoint)
  2063.   ;; Returns the indentation (column #) for the new line after
  2064.   ;; ORGPOINT.  Assumes point to be at the beginning of a block start
  2065.   ;; keyword.
  2066.   (let ((cur-indent (current-indentation))
  2067.         (pos nil))
  2068.     (cond
  2069.      ((save-excursion
  2070.         (forward-word 1)
  2071.         (setq pos (car (ada-search-ignore-string-comment
  2072.                         "[^ \t\n]" nil orgpoint))))
  2073.       (goto-char pos)
  2074.       (save-excursion
  2075.         (funcall (ada-indent-function t) orgpoint)))
  2076.      ;;
  2077.      ;; nothing follows the block-start
  2078.      ;;
  2079.      (t
  2080.       (+ (current-indentation) ada-indent)))))
  2081.  
  2082.  
  2083. (defun ada-get-indent-subprog (orgpoint)
  2084.   ;; Returns the indentation (column #) for the new line after ORGPOINT.
  2085.   ;; Assumes point to be at the beginning of a subprog-/package-declaration.
  2086.   (let ((match-cons nil)
  2087.         (cur-indent (current-indentation))
  2088.         (foundis nil)
  2089.         (addind 0)
  2090.         (fstart (point)))
  2091.     ;;
  2092.     ;; is there an 'is' in front of point ?
  2093.     ;;
  2094.     (if (save-excursion
  2095.           (setq match-cons
  2096.                 (ada-search-ignore-string-comment
  2097.                  "\\<is\\>\\|\\<do\\>" nil orgpoint)))
  2098.         ;;
  2099.         ;; yes, then skip to its end
  2100.         ;;
  2101.         (progn
  2102.           (setq foundis t)
  2103.           (goto-char (cdr match-cons)))
  2104.       ;;
  2105.       ;; no, then goto next non-ws, if there is one in front of point
  2106.       ;;
  2107.       (progn
  2108.         (if (ada-search-ignore-string-comment "[^ \t\n]" nil orgpoint)
  2109.             (ada-goto-next-non-ws)
  2110.           (goto-char orgpoint))))
  2111.  
  2112.     (cond
  2113.      ;;
  2114.      ;; nothing follows 'is'
  2115.      ;;
  2116.      ((and
  2117.        foundis
  2118.        (save-excursion
  2119.          (not (ada-search-ignore-string-comment
  2120.                "[^ \t\n]" nil orgpoint t))))
  2121.       (+ cur-indent ada-indent))
  2122.      ;;
  2123.      ;; is abstract/separate/new ...
  2124.      ;;
  2125.      ((and
  2126.        foundis
  2127.        (save-excursion
  2128.          (setq match-cons
  2129.                (ada-search-ignore-string-comment
  2130.                 "\\<\\(separate\\|new\\|abstract\\)\\>"
  2131.                 nil orgpoint))))
  2132.       (goto-char (car match-cons))
  2133.       (ada-search-ignore-string-comment (concat ada-subprog-start-re
  2134.                                                 "\\|\\<package\\>") t)
  2135.       (ada-get-indent-noindent orgpoint))
  2136.      ;;
  2137.      ;; something follows 'is'
  2138.      ;;
  2139.      ((and
  2140.        foundis
  2141.        (save-excursion
  2142.          (ada-search-ignore-string-comment "[^ \t\n]" nil orgpoint))
  2143.        (ada-goto-next-non-ws)
  2144.       (funcall (ada-indent-function t) orgpoint)))
  2145.      ;;
  2146.      ;; no 'is' but ';'
  2147.      ;;
  2148.      ((save-excursion
  2149.         (ada-search-ignore-string-comment ";" nil orgpoint))
  2150.       cur-indent)
  2151.      ;;
  2152.      ;; no 'is' or ';'
  2153.      ;;
  2154.      (t
  2155.       (+ cur-indent ada-broken-indent)))))
  2156.  
  2157.  
  2158. (defun ada-get-indent-noindent (orgpoint)
  2159.   ;; Returns the indentation (column #) for the new line after ORGPOINT.
  2160.   ;; Assumes point to be at the beginning of a 'noindent statement'.
  2161.   (if (save-excursion
  2162.         (ada-search-ignore-string-comment ";" nil orgpoint))
  2163.       (current-indentation)
  2164.     (+ (current-indentation) ada-broken-indent)))
  2165.  
  2166.  
  2167. (defun ada-get-indent-label (orgpoint)
  2168.   ;; Returns the indentation (column #) for the new line after ORGPOINT.
  2169.   ;; Assumes point to be at the beginning of a label or variable declaration.
  2170.   ;; Checks the context to decide if it's a label or a variable declaration.
  2171.   ;; This check might be a bit slow.
  2172.   (let ((match-cons nil)
  2173.         (cur-indent (current-indentation)))
  2174.     (goto-char (cdr (ada-search-ignore-string-comment ":")))
  2175.     (cond
  2176.      ;;
  2177.      ;; loop label
  2178.      ;;
  2179.      ((save-excursion
  2180.         (setq match-cons (ada-search-ignore-string-comment
  2181.                           ada-loop-start-re nil orgpoint)))
  2182.       (goto-char (car match-cons))
  2183.       (ada-get-indent-loop orgpoint))
  2184.      ;;
  2185.      ;; declare label
  2186.      ;;
  2187.      ((save-excursion
  2188.         (setq match-cons (ada-search-ignore-string-comment
  2189.                           "\\<declare\\>" nil orgpoint)))
  2190.       (save-excursion
  2191.         (goto-char (car match-cons))
  2192.         (+ (current-indentation) ada-indent)))
  2193.      ;;
  2194.      ;; complete statement following colon
  2195.      ;;
  2196.      ((save-excursion
  2197.         (ada-search-ignore-string-comment ";" nil orgpoint))
  2198.       (if (ada-in-decl-p)
  2199.           cur-indent                      ; variable-declaration
  2200.         (- cur-indent ada-label-indent))) ; label
  2201.      ;;
  2202.      ;; broken statement
  2203.      ;;
  2204.      ((save-excursion
  2205.         (ada-search-ignore-string-comment "[^ \t\n]" nil orgpoint))
  2206.       (if (ada-in-decl-p)
  2207.           (+ cur-indent ada-broken-indent)
  2208.         (+ cur-indent ada-broken-indent (- ada-label-indent))))
  2209.      ;;
  2210.      ;; nothing follows colon
  2211.      ;;
  2212.      (t
  2213.       (if (ada-in-decl-p)
  2214.           (+ cur-indent ada-broken-indent)   ; variable-declaration
  2215.         (- cur-indent ada-label-indent)))))) ; label
  2216.  
  2217.  
  2218. (defun ada-get-indent-loop (orgpoint)
  2219.   ;; Returns the indentation (column #) for the new line after ORGPOINT.
  2220.   ;; Assumes point to be at the beginning of a loop statement
  2221.   ;; or (unfortunately) also a for ... use statement.
  2222.   (let ((match-cons nil)
  2223.         (pos (point)))
  2224.     (cond
  2225.  
  2226.      ;;
  2227.      ;; statement complete
  2228.      ;;
  2229.      ((save-excursion
  2230.         (ada-search-ignore-string-comment ";" nil orgpoint))
  2231.       (current-indentation))
  2232.      ;;
  2233.      ;; simple loop
  2234.      ;;
  2235.      ((looking-at "loop\\>")
  2236.       (ada-get-indent-block-start orgpoint))
  2237.  
  2238.      ;;
  2239.      ;; 'for'- loop (or also a for ... use statement)
  2240.      ;;
  2241.      ((looking-at "for\\>")
  2242.       (cond
  2243.        ;;
  2244.        ;; for ... use
  2245.        ;;
  2246.        ((save-excursion
  2247.           (and
  2248.            (goto-char (match-end 0))
  2249.            (ada-search-ignore-string-comment "[^ /n/t]" nil orgpoint)
  2250.            (not (backward-char 1))
  2251.            (not (zerop (skip-chars-forward "_a-zA-Z0-9'")))
  2252.            (ada-search-ignore-string-comment "[^ /n/t]" nil orgpoint)
  2253.            (not (backward-char 1))
  2254.            (looking-at "\\<use\\>")
  2255.            ;;
  2256.            ;; check if there is a 'record' before point
  2257.            ;;
  2258.            (progn
  2259.              (setq match-cons (ada-search-ignore-string-comment
  2260.                                "\\<record\\>" nil orgpoint))
  2261.              t)))
  2262.         (if match-cons
  2263.             (goto-char (car match-cons)))
  2264.         (+ (current-indentation) ada-indent))
  2265.        ;;
  2266.        ;; for..loop
  2267.        ;;
  2268.        ((save-excursion
  2269.           (setq match-cons (ada-search-ignore-string-comment
  2270.                             "\\<loop\\>" nil orgpoint)))
  2271.         (goto-char (car match-cons))
  2272.         ;;
  2273.         ;; indent according to 'loop', if it's first in the line;
  2274.         ;; otherwise to 'for'
  2275.         ;;
  2276.         (if (not (save-excursion
  2277.                    (back-to-indentation)
  2278.                    (looking-at "\\<loop\\>")))
  2279.             (goto-char pos))
  2280.         (+ (current-indentation) ada-indent))
  2281.        ;;
  2282.        ;; for-statement is broken
  2283.        ;;
  2284.        (t
  2285.         (+ (current-indentation) ada-broken-indent))))
  2286.  
  2287.      ;;
  2288.      ;; 'while'-loop
  2289.      ;;
  2290.      ((looking-at "while\\>")
  2291.       ;;
  2292.       ;; while..loop ?
  2293.       ;;
  2294.       (if (save-excursion
  2295.             (setq match-cons (ada-search-ignore-string-comment
  2296.                               "\\<loop\\>" nil orgpoint)))
  2297.  
  2298.           (progn
  2299.             (goto-char (car match-cons))
  2300.             ;;
  2301.             ;; indent according to 'loop', if it's first in the line;
  2302.             ;; otherwise to 'while'.
  2303.             ;;
  2304.             (if (not (save-excursion
  2305.                        (back-to-indentation)
  2306.                        (looking-at "\\<loop\\>")))
  2307.                 (goto-char pos))
  2308.             (+ (current-indentation) ada-indent))
  2309.  
  2310.         (+ (current-indentation) ada-broken-indent))))))
  2311.  
  2312.  
  2313. (defun ada-get-indent-type (orgpoint)
  2314.   ;; Returns the indentation (column #) for the new line after ORGPOINT.
  2315.   ;; Assumes point to be at the beginning of a type statement.
  2316.   (let ((match-dat nil))
  2317.     (cond
  2318.      ;;
  2319.      ;; complete record declaration
  2320.      ;;
  2321.      ((save-excursion
  2322.         (and
  2323.          (setq match-dat (ada-search-ignore-string-comment "\\<end\\>"
  2324.                                                            nil
  2325.                                                            orgpoint))
  2326.          (ada-goto-next-non-ws)
  2327.          (looking-at "\\<record\\>")
  2328.          (forward-word 1)
  2329.          (ada-goto-next-non-ws)
  2330.          (looking-at ";")))
  2331.       (goto-char (car match-dat))
  2332.       (current-indentation))
  2333.      ;;
  2334.      ;; record type
  2335.      ;;
  2336.      ((save-excursion
  2337.         (setq match-dat (ada-search-ignore-string-comment "\\<record\\>"
  2338.                                                           nil
  2339.                                                           orgpoint)))
  2340.       (goto-char (car match-dat))
  2341.       (+ (current-indentation) ada-indent))
  2342.      ;;
  2343.      ;; complete type declaration
  2344.      ;;
  2345.      ((save-excursion
  2346.         (ada-search-ignore-string-comment ";" nil orgpoint))
  2347.       (current-indentation))
  2348.      ;;
  2349.      ;; "type ... is", but not "type ... is ...", which is broken
  2350.      ;;
  2351.      ((save-excursion
  2352.     (and
  2353.      (ada-search-ignore-string-comment "\\<is\\>" nil orgpoint)
  2354.      (not (ada-search-ignore-string-comment "[^ \t\n]" nil orgpoint))))
  2355.       (+ (current-indentation) ada-indent))
  2356.      ;;
  2357.      ;; broken statement
  2358.      ;;
  2359.      (t
  2360.       (+ (current-indentation) ada-broken-indent)))))
  2361.  
  2362.  
  2363. ;;; ---- support-functions for indentation
  2364.  
  2365. ;;; ---- searching and matching
  2366.  
  2367. (defun ada-goto-stmt-start (&optional limit)
  2368.   ;; Moves point to the beginning of the statement that point is in or
  2369.   ;; after.  Returns the new position of point.  Beginnings are found
  2370.   ;; by searching for 'ada-end-stmt-re' and then moving to the
  2371.   ;; following non-ws that is not a comment.  LIMIT is actually not
  2372.   ;; used by the indentation functions.
  2373.   (let ((match-dat nil)
  2374.         (orgpoint (point)))
  2375.  
  2376.     (setq match-dat (ada-search-prev-end-stmt limit))
  2377.     (if match-dat
  2378.         ;;
  2379.         ;; found a previous end-statement => check if anything follows
  2380.         ;;
  2381.         (progn
  2382.           (if (not
  2383.                (save-excursion
  2384.                  (goto-char (cdr match-dat))
  2385.                  (ada-search-ignore-string-comment
  2386.                   "[^ \t\n]" nil orgpoint)))
  2387.               ;;
  2388.               ;; nothing follows => it's the end-statement directly in
  2389.               ;;                    front of point => search again
  2390.               ;;
  2391.               (setq match-dat (ada-search-prev-end-stmt limit)))
  2392.           ;;
  2393.           ;; if found the correct end-stetement => goto next non-ws
  2394.           ;;
  2395.           (if match-dat
  2396.               (goto-char (cdr match-dat)))
  2397.           (ada-goto-next-non-ws))
  2398.  
  2399.       ;;
  2400.       ;; no previous end-statement => we are at the beginning of the
  2401.       ;;                              accessible part of the buffer
  2402.       ;;
  2403.       (progn
  2404.         (goto-char (point-min))
  2405.         ;;
  2406.         ;; skip to the very first statement, if there is one
  2407.         ;;
  2408.         (if (setq match-dat
  2409.                   (ada-search-ignore-string-comment
  2410.                    "[^ \t\n]" nil orgpoint))
  2411.             (goto-char (car match-dat))
  2412.           (goto-char orgpoint))))
  2413.  
  2414.  
  2415.     (point)))
  2416.  
  2417.  
  2418. (defun ada-search-prev-end-stmt (&optional limit)
  2419.   ;; Moves point to previous end-statement.  Returns a cons cell whose
  2420.   ;; car is the beginning and whose cdr the end of the match.
  2421.   ;; End-statements are defined by 'ada-end-stmt-re'.  Checks for
  2422.   ;; certain keywords if they follow 'end', which means they are no
  2423.   ;; end-statement there.
  2424.   (let ((match-dat nil)
  2425.         (pos nil)
  2426.         (found nil))
  2427.     ;;
  2428.     ;; search until found or beginning-of-buffer
  2429.     ;;
  2430.     (while
  2431.         (and
  2432.          (not found)
  2433.          (setq match-dat (ada-search-ignore-string-comment ada-end-stmt-re
  2434.                                                            t
  2435.                                                            limit)))
  2436.  
  2437.       (goto-char (car match-dat))
  2438.  
  2439.       (if (not (ada-in-open-paren-p))
  2440.           ;;
  2441.           ;; check if there is an 'end' in front of the match
  2442.           ;;
  2443.           (if (not (and
  2444.                     (looking-at "\\<\\(record\\|loop\\|select\\)\\>")
  2445.                     (save-excursion
  2446.                       (ada-goto-previous-word)
  2447.                       (looking-at "\\<end\\>"))))
  2448.               (setq found t)
  2449.  
  2450.             (backward-word 1)))) ; end of loop
  2451.  
  2452.     (if found
  2453.         match-dat
  2454.       nil)))
  2455.  
  2456.  
  2457. (defun ada-goto-next-non-ws (&optional limit)
  2458.   ;; Skips whitespaces, newlines and comments to next non-ws
  2459.   ;; character.  Signals an error if there is no more such character
  2460.   ;; and limit is nil.
  2461.   (let ((match-cons nil))
  2462.     (setq match-cons (ada-search-ignore-string-comment
  2463.                       "[^ \t\n]" nil limit t))
  2464.     (if match-cons
  2465.         (goto-char (car match-cons))
  2466.       (if (not limit)
  2467.           (error "no more non-ws")
  2468.         nil))))
  2469.  
  2470.  
  2471. (defun ada-goto-stmt-end (&optional limit)
  2472.   ;; Moves point to the end of the statement that point is in or
  2473.   ;; before.  Returns the new position of point or nil if not found.
  2474.   (if (ada-search-ignore-string-comment ada-end-stmt-re nil limit)
  2475.       (point)
  2476.     nil))
  2477.  
  2478.  
  2479. (defun ada-goto-previous-word ()
  2480.   ;; Moves point to the beginning of the previous word of ada-code.
  2481.   ;; Returns the new position of point or nil if not found.
  2482.   (let ((match-cons nil)
  2483.         (orgpoint (point)))
  2484.     (if (setq match-cons
  2485.               (ada-search-ignore-string-comment "[^ \t\n]" t nil t))
  2486.         ;;
  2487.         ;; move to the beginning of the word found
  2488.         ;;
  2489.         (progn
  2490.           (goto-char (cdr match-cons))
  2491.           (skip-chars-backward "_a-zA-Z0-9")
  2492.           (point))
  2493.       ;;
  2494.       ;; if not found, restore old position of point
  2495.       ;;
  2496.       (progn
  2497.         (goto-char orgpoint)
  2498.         'nil))))
  2499.  
  2500.  
  2501. (defun ada-check-matching-start (keyword)
  2502.   ;; Signals an error if matching block start is not KEYWORD.
  2503.   ;; Moves point to the matching block start.
  2504.   (ada-goto-matching-start 0)
  2505.   (if (not (looking-at (concat "\\<" keyword "\\>")))
  2506.       (error (concat
  2507.               "matching start is not '"
  2508.               keyword "'"))))
  2509.  
  2510.  
  2511. (defun ada-check-defun-name (defun-name)
  2512.   ;; Checks if the name of the matching defun really is DEFUN-NAME.
  2513.   ;; Assumes point to be already positioned by 'ada-goto-matching-start'.
  2514.   ;; Moves point to the beginning of the declaration.
  2515.  
  2516.   ;;
  2517.   ;; 'accept' or 'package' ?
  2518.   ;;
  2519.   (if (not (looking-at "\\<\\(accept\\|package\\|task\\|protected\\)\\>"))
  2520.       (ada-goto-matching-decl-start))
  2521.   ;;
  2522.   ;; 'begin' of 'procedure'/'function'/'task' or 'declare'
  2523.   ;;
  2524.   (save-excursion
  2525.     ;;
  2526.     ;; a named 'declare'-block ?
  2527.     ;;
  2528.     (if (looking-at "\\<declare\\>")
  2529.         (ada-goto-stmt-start)
  2530.       ;;
  2531.       ;; no, => 'procedure'/'function'/'task'/'protected'
  2532.       ;;
  2533.       (progn
  2534.         (forward-word 2)
  2535.         (backward-word 1)
  2536.         ;;
  2537.         ;; skip 'body' 'protected' 'type'
  2538.         ;;
  2539.         (if (looking-at "\\<\\(body\\|type\\)\\>")
  2540.             (forward-word 1))
  2541.         (forward-sexp 1)
  2542.         (backward-sexp 1)))
  2543.     ;;
  2544.     ;; should be looking-at the correct name
  2545.     ;;
  2546.     (if (not (looking-at (concat "\\<" defun-name "\\>")))
  2547.         (error
  2548.          (concat
  2549.           "matching defun has different name: "
  2550.           (buffer-substring
  2551.            (point)
  2552.            (progn
  2553.              (forward-sexp 1)
  2554.              (point))))))))
  2555.  
  2556.  
  2557. (defun ada-goto-matching-decl-start (&optional noerror nogeneric)
  2558.   ;; Moves point to the matching declaration start of the current 'begin'.
  2559.   ;; If NOERROR is non-nil, it only returns nil if no match was found.
  2560.   (let ((nest-count 1)
  2561.         (pos nil)
  2562.         (first t)
  2563.         (flag nil))
  2564.     ;;
  2565.     ;; search backward for interesting keywords
  2566.     ;;
  2567.     (while (and
  2568.             (not (zerop nest-count))
  2569.             (ada-search-ignore-string-comment
  2570.              (concat "\\<\\("
  2571.                      "is\\|separate\\|end\\|declare\\|new\\|begin\\|generic"
  2572.                      "\\)\\>") t))
  2573.       ;;
  2574.       ;; calculate nest-depth
  2575.       ;;
  2576.       (cond
  2577.        ;;
  2578.        ((looking-at "end")
  2579.         (ada-goto-matching-start 1 noerror)
  2580.         (if (looking-at "begin")
  2581.             (setq nest-count (1+ nest-count))))
  2582.        ;;
  2583.        ((looking-at "declare\\|generic")
  2584.         (setq nest-count (1- nest-count))
  2585.         (setq first nil))
  2586.        ;;
  2587.        ((looking-at "is")
  2588.         ;; check if it is only a type definition
  2589.         (if (save-excursion
  2590.               (ada-goto-previous-word)
  2591.               (skip-chars-backward "a-zA-Z0-9_.'")
  2592.               (if (save-excursion
  2593.                     (backward-char 1)
  2594.                     (looking-at ")"))
  2595.                   (progn
  2596.                     (forward-char 1)
  2597.                     (backward-sexp 1)
  2598.                     (skip-chars-backward "a-zA-Z0-9_.'")
  2599.                     ))
  2600.               (ada-goto-previous-word)
  2601.               (looking-at "\\<type\\>")) ; end of save-excursion
  2602.             (goto-char (match-beginning 0))
  2603.           (progn
  2604.             (setq nest-count (1- nest-count))
  2605.             (setq first nil))))
  2606.  
  2607.        ;;
  2608.        ((looking-at "new")
  2609.         (if (save-excursion
  2610.               (ada-goto-previous-word)
  2611.               (looking-at "is"))
  2612.             (goto-char (match-beginning 0))))
  2613.        ;;
  2614.        ((and first
  2615.              (looking-at "begin"))
  2616.         (setq nest-count 0)
  2617.         (setq flag t))
  2618.        ;;
  2619.        (t
  2620.         (setq nest-count (1+ nest-count))
  2621.         (setq first nil)))
  2622.  
  2623.       )  ;; end of loop
  2624.  
  2625.     ;; check if declaration-start is really found
  2626.     (if (not
  2627.          (and
  2628.           (zerop nest-count)
  2629.           (not flag)
  2630.           (progn
  2631.             (if (looking-at "is")
  2632.                   (ada-search-ignore-string-comment
  2633.                    ada-subprog-start-re t)
  2634.               (looking-at "declare\\|generic")))))
  2635.         (if noerror nil
  2636.           (error "no matching procedure/function/task/declare/package"))
  2637.       t)))
  2638.  
  2639.  
  2640. (defun ada-goto-matching-start (&optional nest-level noerror gotothen)
  2641.   ;; Moves point to the beginning of a block-start.  Which block
  2642.   ;; depends on the value of NEST-LEVEL, which defaults to zero.  If
  2643.   ;; NOERROR is non-nil, it only returns nil if no matching start was
  2644.   ;; found.  If GOTOTHEN is non-nil, point moves to the 'then'
  2645.   ;; following 'if'.
  2646.   (let ((nest-count (if nest-level nest-level 0))
  2647.         (found nil)
  2648.         (pos nil))
  2649.  
  2650.     ;;
  2651.     ;; search backward for interesting keywords
  2652.     ;;
  2653.     (while (and
  2654.             (not found)
  2655.             (ada-search-ignore-string-comment
  2656.              (concat "\\<\\("
  2657.                      "end\\|loop\\|select\\|begin\\|case\\|do\\|"
  2658.                      "if\\|task\\|package\\|record\\|protected\\)\\>")
  2659.              t))
  2660.  
  2661.       ;;
  2662.       ;; calculate nest-depth
  2663.       ;;
  2664.       (cond
  2665.        ;; found block end => increase nest depth
  2666.        ((looking-at "end")
  2667.         (setq nest-count (1+ nest-count)))
  2668.        ;; found loop/select/record/case/if => check if it starts or
  2669.        ;; ends a block
  2670.        ((looking-at "loop\\|select\\|record\\|case\\|if")
  2671.         (setq pos (point))
  2672.         (save-excursion
  2673.           ;;
  2674.           ;; check if keyword follows 'end'
  2675.           ;;
  2676.           (ada-goto-previous-word)
  2677.           (if (looking-at "\\<end\\>")
  2678.               ;; it ends a block => increase nest depth
  2679.               (progn
  2680.                 (setq nest-count (1+ nest-count))
  2681.                 (setq pos (point)))
  2682.             ;; it starts a block => decrease nest depth
  2683.             (setq nest-count (1- nest-count))))
  2684.         (goto-char pos))
  2685.        ;; found package start => check if it really is a block
  2686.        ((looking-at "package")
  2687.         (save-excursion
  2688.           (ada-search-ignore-string-comment "\\<is\\>")
  2689.           (ada-goto-next-non-ws)
  2690.           ;; ignore it if it is only a declaration with 'new'
  2691.           (if (not (looking-at "\\<new\\>"))
  2692.               (setq nest-count (1- nest-count)))))
  2693.        ;; found task start => check if it has a body
  2694.        ((looking-at "task")
  2695.         (save-excursion
  2696.           (forward-word 1)
  2697.           (ada-goto-next-non-ws)
  2698.           ;; ignore it if it has no body
  2699.           (if (not (looking-at "\\<body\\>"))
  2700.               (setq nest-count (1- nest-count)))))
  2701.        ;; all the other block starts
  2702.        (t
  2703.         (setq nest-count (1- nest-count)))) ; end of 'cond'
  2704.  
  2705.       ;; match is found, if nest-depth is zero
  2706.       ;;
  2707.       (setq found (zerop nest-count))) ; end of loop
  2708.  
  2709.     (if found
  2710.         ;;
  2711.         ;; match found => is there anything else to do ?
  2712.         ;;
  2713.         (progn
  2714.           (cond
  2715.            ;;
  2716.            ;; found 'if' => skip to 'then', if it's on a separate line
  2717.            ;;                               and GOTOTHEN is non-nil
  2718.            ;;
  2719.            ((and
  2720.              gotothen
  2721.              (looking-at "if")
  2722.              (save-excursion
  2723.                (ada-search-ignore-string-comment "\\<then\\>" nil nil)
  2724.                (back-to-indentation)
  2725.                (looking-at "\\<then\\>")))
  2726.             (goto-char (match-beginning 0)))
  2727.            ;;
  2728.            ;; found 'do' => skip back to 'accept'
  2729.            ;;
  2730.            ((looking-at "do")
  2731.             (if (not (ada-search-ignore-string-comment "\\<accept\\>" t nil))
  2732.                 (error "missing 'accept' in front of 'do'"))))
  2733.           (point))
  2734.  
  2735.       (if noerror
  2736.           nil
  2737.         (error "no matching start")))))
  2738.  
  2739.  
  2740. (defun ada-goto-matching-end (&optional nest-level noerror)
  2741.   ;; Moves point to the end of a block.  Which block depends on the
  2742.   ;; value of NEST-LEVEL, which defaults to zero.  If NOERROR is
  2743.   ;; non-nil, it only returns nil if found no matching start.
  2744.   (let ((nest-count (if nest-level nest-level 0))
  2745.         (found nil))
  2746.  
  2747.     ;;
  2748.     ;; search forward for interesting keywords
  2749.     ;;
  2750.     (while (and
  2751.             (not found)
  2752.             (ada-search-ignore-string-comment
  2753.              (concat "\\<\\(end\\|loop\\|select\\|begin\\|case\\|"
  2754.                      "if\\|task\\|package\\|record\\|do\\)\\>")))
  2755.  
  2756.       ;;
  2757.       ;; calculate nest-depth
  2758.       ;;
  2759.       (backward-word 1)
  2760.       (cond
  2761.        ;; found block end => decrease nest depth
  2762.        ((looking-at "\\<end\\>")
  2763.         (setq nest-count (1- nest-count))
  2764.         ;; skip the following keyword
  2765.         (if (progn
  2766.               (skip-chars-forward "end")
  2767.               (ada-goto-next-non-ws)
  2768.               (looking-at "\\<\\(loop\\|select\\|record\\|case\\|if\\)\\>"))
  2769.             (forward-word 1)))
  2770.        ;; found package start => check if it really starts a block
  2771.        ((looking-at "\\<package\\>")
  2772.         (ada-search-ignore-string-comment "\\<is\\>")
  2773.         (ada-goto-next-non-ws)
  2774.         ;; ignore and skip it if it is only a 'new' package
  2775.         (if (not (looking-at "\\<new\\>"))
  2776.             (setq nest-count (1+ nest-count))
  2777.           (skip-chars-forward "new")))
  2778.        ;; all the other block starts
  2779.        (t
  2780.         (setq nest-count (1+ nest-count))
  2781.         (forward-word 1))) ; end of 'cond'
  2782.  
  2783.       ;; match is found, if nest-depth is zero
  2784.       ;;
  2785.       (setq found (zerop nest-count))) ; end of loop
  2786.  
  2787.     (if (not found)
  2788.         (if noerror
  2789.             nil
  2790.           (error "no matching end"))
  2791.       t)))
  2792.  
  2793.  
  2794. (defun ada-forward-sexp-ignore-comment ()
  2795.   ;; Skips one sexp forward, ignoring comments.
  2796.   (while (looking-at "[ \t\n]*--")
  2797.     (skip-chars-forward "[ \t\n]")
  2798.     (end-of-line))
  2799.   (forward-sexp 1))
  2800.  
  2801.  
  2802. (defun ada-search-ignore-string-comment
  2803.   (search-re &optional backward limit paramlists)
  2804.   ;; Regexp-Search for SEARCH-RE, ignoring comments, strings and
  2805.   ;; parameter lists, if PARAMLISTS is nil. Returns a cons cell of
  2806.   ;; begin and end of match data or nil, if not found.
  2807.   (let ((found nil)
  2808.         (begin nil)
  2809.         (end nil)
  2810.         (pos nil)
  2811.         (search-func
  2812.          (if backward 're-search-backward
  2813.            're-search-forward)))
  2814.  
  2815.     ;;
  2816.     ;; search until found or end-of-buffer
  2817.     ;;
  2818.     (while (and (not found)
  2819.                 (funcall search-func search-re limit 1))
  2820.       (setq begin (match-beginning 0))
  2821.       (setq end (match-end 0))
  2822.  
  2823.       (cond
  2824.        ;;
  2825.        ;; found in comment => skip it
  2826.        ;;
  2827.        ((ada-in-comment-p)
  2828.         (if backward
  2829.             (progn
  2830.               (re-search-backward "--" nil 1)
  2831.               (goto-char (match-beginning 0)))
  2832.           (progn
  2833.             (forward-line 1)
  2834.             (beginning-of-line))))
  2835.        ;;
  2836.        ;; found in string => skip it
  2837.        ;;
  2838.        ((ada-in-string-p)
  2839.         (if backward
  2840.             (progn
  2841.               (re-search-backward "\"" nil 1) ; "\"\\|#" don't treat #
  2842.               (goto-char (match-beginning 0))))
  2843.         (re-search-forward "\"" nil 1))
  2844.        ;;
  2845.        ;; found character constant => ignore it
  2846.        ;;
  2847.        ((save-excursion
  2848.           (setq pos (- (point) (if backward 1 2)))
  2849.           (and (char-after pos)
  2850.                (= (char-after pos) ?')
  2851.                (= (char-after (+ pos 2)) ?')))
  2852.         ())
  2853.        ;;
  2854.        ;; found a parameter-list but should ignore it => skip it
  2855.        ;;
  2856.        ((and (not paramlists)
  2857.              (ada-in-paramlist-p))
  2858.         (if backward
  2859.             (ada-search-ignore-string-comment "(" t nil t)))
  2860.        ;;
  2861.        ;; directly in front of a comment => skip it, if searching forward
  2862.        ;;
  2863.        ((save-excursion
  2864.           (goto-char begin)
  2865.           (looking-at "--"))
  2866.         (if (not backward)
  2867.             (progn
  2868.               (forward-line 1)
  2869.               (beginning-of-line))))
  2870.        ;;
  2871.        ;; found what we were looking for
  2872.        ;;
  2873.        (t
  2874.         (setq found t)))) ; end of loop
  2875.  
  2876.     (if found
  2877.         (cons begin end)
  2878.       nil)))
  2879.  
  2880.  
  2881. (defun ada-search-but-not (search-re not-search-re &optional backward limit)
  2882.   ;; Searches SEARCH-RE, ignoring parts of NOT-SEARCH-RE, strings,
  2883.   ;; comments and parameter-lists.
  2884.   (let ((begin nil)
  2885.         (end nil)
  2886.         (begin-not nil)
  2887.         (begin-end nil)
  2888.         (end-not nil)
  2889.         (ret-cons nil)
  2890.         (found nil))
  2891.  
  2892.     ;;
  2893.     ;; search until found or end-of-buffer
  2894.     ;;
  2895.     (while (and
  2896.             (not found)
  2897.             (save-excursion
  2898.               (setq ret-cons
  2899.                     (ada-search-ignore-string-comment search-re
  2900.                                                       backward limit))
  2901.               (if (consp ret-cons)
  2902.                   (progn
  2903.                     (setq begin (car ret-cons))
  2904.                     (setq end (cdr ret-cons))
  2905.                     t)
  2906.                 nil)))
  2907.  
  2908.       (if (or
  2909.            ;;
  2910.            ;; if no NO-SEARCH-RE was found
  2911.            ;;
  2912.            (not
  2913.             (save-excursion
  2914.               (setq ret-cons
  2915.                     (ada-search-ignore-string-comment not-search-re
  2916.                                                       backward nil))
  2917.               (if (consp ret-cons)
  2918.                   (progn
  2919.                     (setq begin-not (car ret-cons))
  2920.                     (setq end-not (cdr ret-cons))
  2921.                     t)
  2922.                 nil)))
  2923.            ;;
  2924.            ;;  or this NO-SEARCH-RE is not a part of the SEARCH-RE
  2925.            ;;  found before.
  2926.            ;;
  2927.            (or
  2928.             (<= end-not begin)
  2929.             (>= begin-not end)))
  2930.  
  2931.           (setq found t)
  2932.  
  2933.         ;;
  2934.         ;; not found the correct match => skip this match
  2935.         ;;
  2936.         (goto-char (if backward
  2937.                        begin
  2938.                      end)))) ; end of loop
  2939.  
  2940.     (if found
  2941.         (progn
  2942.           (goto-char begin)
  2943.           (cons begin end))
  2944.       nil)))
  2945.  
  2946.  
  2947. (defun ada-goto-prev-nonblank-line ( &optional ignore-comment)
  2948.   ;; Moves point to the beginning of previous non-blank line,
  2949.   ;; ignoring comments if IGNORE-COMMENT is non-nil.
  2950.   ;; It returns t if a matching line was found.
  2951.   (let ((notfound t)
  2952.         (newpoint nil))
  2953.  
  2954.     (save-excursion
  2955.       ;;
  2956.       ;; backward one line, if there is one
  2957.       ;;
  2958.       (if (zerop (forward-line -1))
  2959.           ;;
  2960.           ;; there is some kind of previous line
  2961.           ;;
  2962.           (progn
  2963.             (beginning-of-line)
  2964.             (setq newpoint (point))
  2965.  
  2966.             ;;
  2967.             ;; search until found or beginning-of-buffer
  2968.             ;;
  2969.             (while (and (setq notfound
  2970.                               (or (looking-at "[ \t]*$")
  2971.                                   (and (looking-at "[ \t]*--")
  2972.                                        ignore-comment)))
  2973.                         (not (ada-in-limit-line-p)))
  2974.               (forward-line -1)
  2975.               ;;(beginning-of-line)
  2976.               (setq newpoint (point))) ; end of loop
  2977.  
  2978.             )) ; end of if
  2979.  
  2980.       ) ; end of save-excursion
  2981.  
  2982.     (if notfound nil
  2983.       (progn
  2984.         (goto-char newpoint)
  2985.         t))))
  2986.  
  2987.  
  2988. (defun ada-goto-next-nonblank-line ( &optional ignore-comment)
  2989.   ;; Moves point to next non-blank line,
  2990.   ;; ignoring comments if IGNORE-COMMENT is non-nil.
  2991.   ;; It returns t if a matching line was found.
  2992.   (let ((notfound t)
  2993.         (newpoint nil))
  2994.  
  2995.     (save-excursion
  2996.     ;;
  2997.     ;; forward one line
  2998.     ;;
  2999.       (if (zerop (forward-line 1))
  3000.           ;;
  3001.           ;; there is some kind of previous line
  3002.           ;;
  3003.           (progn
  3004.             (beginning-of-line)
  3005.             (setq newpoint (point))
  3006.  
  3007.             ;;
  3008.             ;; search until found or end-of-buffer
  3009.             ;;
  3010.             (while (and (setq notfound
  3011.                               (or (looking-at "[ \t]*$")
  3012.                                   (and (looking-at "[ \t]*--")
  3013.                                        ignore-comment)))
  3014.                         (not (ada-in-limit-line-p)))
  3015.               (forward-line 1)
  3016.               (beginning-of-line)
  3017.               (setq newpoint (point))) ; end of loop
  3018.  
  3019.             )) ; end of if
  3020.  
  3021.       ) ; end of save-excursion
  3022.  
  3023.     (if notfound nil
  3024.       (progn
  3025.         (goto-char newpoint)
  3026.         t))))
  3027.  
  3028.  
  3029. ;; ---- boolean functions for indentation
  3030.  
  3031. (defun ada-in-decl-p ()
  3032.   ;; Returns t if point is inside a declarative part.
  3033.   ;; Assumes point to be at the end of a statement.
  3034.   (or
  3035.    (ada-in-paramlist-p)
  3036.    (save-excursion
  3037.      (ada-goto-matching-decl-start t))))
  3038.  
  3039.  
  3040. (defun ada-looking-at-semi-or ()
  3041.   ;; Returns t if looking-at an 'or' following a semicolon.
  3042.   (save-excursion
  3043.     (and (looking-at "\\<or\\>")
  3044.          (progn
  3045.            (forward-word 1)
  3046.            (ada-goto-stmt-start)
  3047.            (looking-at "\\<or\\>")))))
  3048.  
  3049.  
  3050. (defun ada-looking-at-semi-private ()
  3051.   ;; Returns t if looking-at an 'private' following a semicolon.
  3052.   (save-excursion
  3053.     (and (looking-at "\\<private\\>")
  3054.          (progn
  3055.            (forward-word 1)
  3056.            (ada-goto-stmt-start)
  3057.            (looking-at "\\<private\\>")))))
  3058.  
  3059.  
  3060. ;;; make a faster??? ada-in-limit-line-p not using count-lines
  3061. (defun ada-in-limit-line-p ()
  3062.   ;; return t if point is in first or last accessible line.
  3063.   (or (save-excursion (beginning-of-line) (= (point-min) (point)))
  3064.       (save-excursion (end-of-line) (= (point-max) (point)))))
  3065.  
  3066.  
  3067. (defun ada-in-comment-p ()
  3068.   ;; Returns t if inside a comment.
  3069.   (save-excursion (and (re-search-backward "\\(--\\|\n\\)" nil 1)
  3070.                        (looking-at "-"))))
  3071.  
  3072.  
  3073. (defun ada-in-string-p ()
  3074.   ;; Returns t if point is inside a string
  3075.   ;; (Taken from pascal-mode.el, modified by MH).
  3076.   (save-excursion
  3077.     (and
  3078.      (nth 3 (parse-partial-sexp
  3079.              (save-excursion
  3080.                (beginning-of-line)
  3081.                (point)) (point)))
  3082.      ;; check if 'string quote' is only a character constant
  3083.      (progn
  3084.        (re-search-backward "\"" nil t) ; # not a string delimiter anymore
  3085.        (not (= (char-after (1- (point))) ?'))))))
  3086.  
  3087.  
  3088. (defun ada-in-string-or-comment-p ()
  3089.   ;; Returns t if point is inside a string or a comment.
  3090.   (or (ada-in-comment-p)
  3091.       (ada-in-string-p)))
  3092.  
  3093.  
  3094. (defun ada-in-paramlist-p ()
  3095.   ;; Returns t if point is inside a parameter-list
  3096.   ;; following 'function'/'procedure'/'package'.
  3097.   (save-excursion
  3098.     (and
  3099.      (re-search-backward "(\\|)" nil t)
  3100.      ;; inside parentheses ?
  3101.      (looking-at "(")
  3102.      (backward-word 2)
  3103.      ;; right keyword before paranthesis ?
  3104.      (looking-at (concat "\\<\\("
  3105.                          "procedure\\|function\\|body\\|package\\|"
  3106.                          "task\\|entry\\|accept\\)\\>"))
  3107.      (re-search-forward ")\\|:" nil t)
  3108.      ;; at least one ':' inside the parentheses ?
  3109.      (not (backward-char 1))
  3110.      (looking-at ":"))))
  3111.  
  3112.  
  3113. ;; not really a boolean function ...
  3114. (defun ada-in-open-paren-p ()
  3115.   ;; If point is somewhere behind an open parenthesis not yet closed,
  3116.   ;; it returns the column # of the first non-ws behind this open
  3117.   ;; parenthesis, otherwise nil."
  3118.  
  3119.   (let ((start (if (< (point) ada-search-paren-char-count-limit)
  3120.                    1
  3121.                  (- (point) ada-search-paren-char-count-limit)))
  3122.         parse-result
  3123.         (col nil))
  3124.     (setq parse-result (parse-partial-sexp start (point)))
  3125.     (if (nth 1 parse-result)
  3126.         (save-excursion
  3127.           (goto-char (1+ (nth 1 parse-result)))
  3128.           (if (save-excursion
  3129.                 (re-search-forward "[^ \t]" nil 1)
  3130.                 (backward-char 1)
  3131.                 (and
  3132.                  (not (looking-at "\n"))
  3133.                  (setq col (current-column))))
  3134.               col
  3135.             (current-column)))
  3136.       nil)))
  3137.  
  3138.  
  3139.  
  3140. ;;;----------------------;;;
  3141. ;;; Behaviour Of TAB Key ;;;
  3142. ;;;----------------------;;;
  3143.  
  3144. (defun ada-tab ()
  3145.   "Do indenting or tabbing according to `ada-tab-policy'."
  3146.   (interactive)
  3147.   (cond ((eq ada-tab-policy 'indent-and-tab) (error "not implemented"))
  3148.         ;; ada-indent-and-tab
  3149.         ((eq ada-tab-policy 'indent-rigidly) (ada-tab-hard))
  3150.         ((eq ada-tab-policy 'indent-auto) (ada-indent-current))
  3151.         ((eq ada-tab-policy 'gei) (ada-tab-gei))
  3152.         ((eq ada-tab-policy 'indent-af) (af-indent-line)) ; GEB
  3153.         ((eq ada-tab-policy 'always-tab) (error "not implemented"))
  3154.         ))
  3155.  
  3156.  
  3157. (defun ada-untab (arg)
  3158.   "Delete leading indenting according to `ada-tab-policy'."
  3159.   (interactive "P")
  3160.   (cond ((eq ada-tab-policy 'indent-rigidly) (ada-untab-hard))
  3161.         ((eq ada-tab-policy 'indent-af) (backward-delete-char-untabify ; GEB
  3162.                                          (prefix-numeric-value arg) ; GEB
  3163.                                          arg)) ; GEB
  3164.         ((eq ada-tab-policy 'indent-auto) (error "not implemented"))
  3165.         ((eq ada-tab-policy 'always-tab) (error "not implemented"))
  3166.         ))
  3167.  
  3168.  
  3169. (defun ada-indent-current-function ()
  3170.   "Ada Mode version of the indent-line-function."
  3171.   (interactive "*")
  3172.   (let ((starting-point (point-marker)))
  3173.     (ada-beginning-of-line)
  3174.     (ada-tab)
  3175.     (if (< (point) starting-point)
  3176.         (goto-char starting-point))
  3177.     (set-marker starting-point nil)
  3178.     ))
  3179.  
  3180.  
  3181. (defun ada-tab-hard ()
  3182.   "Indent current line to next tab stop."
  3183.   (interactive)
  3184.   (save-excursion
  3185.     (beginning-of-line)
  3186.     (insert-char ?  ada-indent))
  3187.   (if (save-excursion (= (point) (progn (beginning-of-line) (point))))
  3188.       (forward-char ada-indent)))
  3189.  
  3190.  
  3191. (defun ada-untab-hard ()
  3192.   "indent current line to previous tab stop."
  3193.   (interactive)
  3194.   (let  ((bol (save-excursion (progn (beginning-of-line) (point))))
  3195.         (eol (save-excursion (progn (end-of-line) (point)))))
  3196.     (indent-rigidly bol eol  (- 0 ada-indent))))
  3197.  
  3198.  
  3199.  
  3200. ;;;---------------;;;
  3201. ;;; Miscellaneous ;;;
  3202. ;;;---------------;;;
  3203.  
  3204. (defun ada-remove-trailing-spaces  ()
  3205. ;; remove all trailing spaces at the end of lines.
  3206.  "remove trailing spaces in the whole buffer."
  3207.   (interactive)
  3208.   (save-excursion
  3209.     (goto-char (point-min))
  3210.     (while (re-search-forward "[ \t]+$" nil t)
  3211.       (replace-match "" nil nil))))
  3212.  
  3213.  
  3214. (defun ada-untabify-buffer ()
  3215. ;; change all tabs to spaces
  3216.   (save-excursion
  3217.     (untabify (point-min) (point-max))))
  3218.  
  3219.  
  3220. (defun ada-uncomment-region (beg end)
  3221.   "delete comment-start at the beginning of a line in the region."
  3222.   (interactive "r")
  3223.   (comment-region beg end -1))
  3224.  
  3225.  
  3226. ;; define a function to support find-file.el if loaded
  3227. (defun ada-ff-other-window ()
  3228.   "Find other file in other window using ff-find-other-file."
  3229.   (interactive)
  3230.   (and (fboundp 'ff-find-other-file)
  3231.        (ff-find-other-file t)))
  3232.  
  3233.  
  3234. ;;;-------------------------------;;;
  3235. ;;; Moving To Procedures/Packages ;;;
  3236. ;;;-------------------------------;;;
  3237.  
  3238. (defun ada-next-procedure ()
  3239.   "Moves point to next procedure."
  3240.   (interactive)
  3241.   (end-of-line)
  3242.   (if (re-search-forward ada-procedure-start-regexp nil t)
  3243.       (goto-char (match-beginning 1))
  3244.     (error "No more functions/procedures/tasks")))
  3245.  
  3246. (defun ada-previous-procedure ()
  3247.   "Moves point to previous procedure."
  3248.   (interactive)
  3249.   (beginning-of-line)
  3250.   (if (re-search-backward ada-procedure-start-regexp nil t)
  3251.       (goto-char (match-beginning 1))
  3252.     (error "No more functions/procedures/tasks")))
  3253.  
  3254. (defun ada-next-package ()
  3255.   "Moves point to next package."
  3256.   (interactive)
  3257.   (end-of-line)
  3258.   (if (re-search-forward ada-package-start-regexp nil t)
  3259.       (goto-char (match-beginning 1))
  3260.     (error "No more packages")))
  3261.  
  3262. (defun ada-previous-package ()
  3263.   "Moves point to previous package."
  3264.   (interactive)
  3265.   (beginning-of-line)
  3266.   (if (re-search-backward ada-package-start-regexp nil t)
  3267.       (goto-char (match-beginning 1))
  3268.     (error "No more packages")))
  3269.  
  3270.  
  3271. ;;;-----------------------
  3272. ;;; define keymap for Ada
  3273. ;;;-----------------------
  3274.  
  3275. (if (not ada-mode-map)
  3276.     (progn
  3277.       (setq ada-mode-map (make-sparse-keymap))
  3278.  
  3279.       ;; Indentation and Formatting
  3280.       (define-key ada-mode-map "\C-j"     'ada-indent-newline-indent)
  3281.       (define-key ada-mode-map "\t"       'ada-tab)
  3282.       (define-key ada-mode-map "\C-c\C-l" 'ada-indent-region)
  3283.       (if (ada-xemacs)
  3284.       (define-key ada-mode-map '(shift tab)    'ada-untab)
  3285.     (define-key ada-mode-map [S-tab]    'ada-untab))
  3286.       (define-key ada-mode-map "\C-c\C-f" 'ada-format-paramlist)
  3287.       (define-key ada-mode-map "\C-c\C-p" 'ada-call-pretty-printer)
  3288. ;;; We don't want to make meta-characters case-specific.
  3289. ;;;   (define-key ada-mode-map "\M-Q"     'ada-fill-comment-paragraph-justify)
  3290.       (define-key ada-mode-map "\M-\C-q"  'ada-fill-comment-paragraph-postfix)
  3291.  
  3292.       ;; Movement
  3293. ;;; It isn't good to redefine these.  What should be done instead?  -- rms.
  3294. ;;;   (define-key ada-mode-map "\M-e"     'ada-next-package)
  3295. ;;;   (define-key ada-mode-map "\M-a"     'ada-previous-package)
  3296.       (define-key ada-mode-map "\M-\C-e"  'ada-next-procedure)
  3297.       (define-key ada-mode-map "\M-\C-a"  'ada-previous-procedure)
  3298.       (define-key ada-mode-map "\C-c\C-a" 'ada-move-to-start)
  3299.       (define-key ada-mode-map "\C-c\C-e" 'ada-move-to-end)
  3300.  
  3301.       ;; Compilation
  3302.       (define-key ada-mode-map "\C-c\C-c" 'compile)
  3303.  
  3304.       ;; Casing
  3305.       (define-key ada-mode-map "\C-c\C-r" 'ada-adjust-case-region)
  3306.       (define-key ada-mode-map "\C-c\C-b" 'ada-adjust-case-buffer)
  3307.  
  3308.       (define-key ada-mode-map "\177"     'backward-delete-char-untabify)
  3309.  
  3310.       ;; Use predefined function of emacs19 for comments (RE)
  3311.       (define-key ada-mode-map "\C-c;"    'comment-region)
  3312.       (define-key ada-mode-map "\C-c:"    'ada-uncomment-region)
  3313.  
  3314.       ;; Change basic functionality
  3315.  
  3316.       ;; substitute-key-definition is not defined equally in GNU Emacs
  3317.       ;; and XEmacs, you cannot put in an optional 4th parameter in
  3318.       ;; XEmacs.  I don't think it's necessary, so I leave it out for
  3319.       ;; GNU Emacs as well.  If you encounter any problems with the
  3320.       ;; following three functions, please tell me. RE
  3321.       (mapcar (function (lambda (pair)
  3322.               (substitute-key-definition (car pair) (cdr pair)
  3323.                              ada-mode-map)))
  3324.           '((beginning-of-line      . ada-beginning-of-line)
  3325.         (end-of-line            . ada-end-of-line)
  3326.         (forward-to-indentation . ada-forward-to-indentation)
  3327.         ))
  3328.       ;; else GNU Emacs
  3329.       ;;(mapcar (lambda (pair)
  3330.       ;;             (substitute-key-definition (car pair) (cdr pair)
  3331.       ;;                   ada-mode-map global-map))
  3332.  
  3333.       ))
  3334.  
  3335.  
  3336. ;;;-------------------
  3337. ;;; define menu 'Ada'
  3338. ;;;-------------------
  3339.  
  3340. (require 'easymenu)
  3341.  
  3342. (defun ada-add-ada-menu ()
  3343.   "Adds the menu 'Ada' to the menu-bar in Ada Mode."
  3344.   (easy-menu-define ada-mode-menu ada-mode-map "Menu keymap for Ada mode."
  3345.                     '("Ada"
  3346.                       ["Next Package" ada-next-package t]
  3347.                       ["Previous Package" ada-previous-package t]
  3348.                       ["Next Procedure" ada-next-procedure t]
  3349.                       ["Previous Procedure" ada-previous-procedure t]
  3350.                       ["Goto Start" ada-move-to-start t]
  3351.                       ["Goto End" ada-move-to-end t]
  3352.                       ["------------------" nil nil]
  3353.                       ["Indent Current Line (TAB)"
  3354.                        ada-indent-current-function t]
  3355.                       ["Indent Lines in Region" ada-indent-region t]
  3356.                       ["Format Parameter List" ada-format-paramlist t]
  3357.                       ["Pretty Print Buffer" ada-call-pretty-printer t]
  3358.                       ["------------" nil nil]
  3359.                       ["Fill Comment Paragraph"
  3360.                        ada-fill-comment-paragraph t]
  3361.                       ["Justify Comment Paragraph"
  3362.                        ada-fill-comment-paragraph-justify t]
  3363.                       ["Postfix Comment Paragraph"
  3364.                        ada-fill-comment-paragraph-postfix t]
  3365.                       ["------------" nil nil]
  3366.                       ["Adjust Case Region" ada-adjust-case-region t]
  3367.                       ["Adjust Case Buffer" ada-adjust-case-buffer t]
  3368.                       ["----------" nil nil]
  3369.                       ["Comment   Region" comment-region t]
  3370.                       ["Uncomment Region" ada-uncomment-region t]
  3371.                       ["----------------" nil nil]
  3372.                       ["Compile" compile (fboundp 'compile)]
  3373.                       ["Next Error" next-error (fboundp 'next-error)]
  3374.                       ["---------------" nil nil]
  3375.                       ["Index" imenu (fboundp 'imenu)]
  3376.                       ["--------------" nil nil]
  3377.                       ["Other File Other Window" ada-ff-other-window
  3378.                        (fboundp 'ff-find-other-file)]
  3379.                       ["Other File" ff-find-other-file
  3380.                        (fboundp 'ff-find-other-file)]))
  3381.   (if (ada-xemacs) (progn
  3382.                      (easy-menu-add ada-mode-menu)
  3383.                      (setq mode-popup-menu (cons "Ada Mode" ada-mode-menu)))))
  3384.  
  3385.  
  3386.  
  3387. ;;;-------------------------------
  3388. ;;; Define Some Support Functions
  3389. ;;;-------------------------------
  3390.  
  3391. (defun ada-beginning-of-line (&optional arg)
  3392.   (interactive "P")
  3393.   (cond
  3394.    ((eq ada-tab-policy 'indent-af) (af-beginning-of-line arg))
  3395.    (t (beginning-of-line arg))
  3396.    ))
  3397.  
  3398. (defun ada-end-of-line (&optional arg)
  3399.   (interactive "P")
  3400.   (cond
  3401.    ((eq ada-tab-policy 'indent-af) (af-end-of-line arg))
  3402.    (t (end-of-line arg))
  3403.    ))
  3404.  
  3405. (defun ada-current-column ()
  3406.   (cond
  3407.    ((eq ada-tab-policy 'indent-af) (af-current-column))
  3408.    (t (current-column))
  3409.    ))
  3410.  
  3411. (defun ada-forward-to-indentation (&optional arg)
  3412.   (interactive "P")
  3413.   (cond
  3414.    ((eq ada-tab-policy 'indent-af) (af-forward-to-indentation arg))
  3415.    (t (forward-to-indentation arg))
  3416.    ))
  3417.  
  3418. ;;;---------------------------------------------------
  3419. ;;; support for find-file
  3420. ;;;---------------------------------------------------
  3421.  
  3422.  
  3423. ;;;###autoload
  3424. (defun ada-make-filename-from-adaname (adaname)
  3425.   "determine the filename of a package/procedure from its own Ada name."
  3426.   ;; this is done simply by calling gkrunch, when we work with GNAT. It
  3427.   ;; must be a more complex function in other compiler environments.
  3428.   (interactive "s")
  3429.  
  3430.   ;; things that should really be done by the external process
  3431.   ;; since gnat-2.0, gnatk8 can do these things. If you still use a
  3432.   ;; previous version, just uncomment the following lines.
  3433.   (let (krunch-buf)
  3434.     (setq krunch-buf (generate-new-buffer "*gkrunch*"))
  3435.     (save-excursion
  3436.       (set-buffer krunch-buf)
  3437. ;      (insert (downcase adaname))
  3438. ;      (goto-char (point-min))
  3439. ;      (while (search-forward "." nil t)
  3440. ;        (replace-match "-" nil t))
  3441. ;      (setq adaname (buffer-substring (point-min)
  3442. ;                                      (progn
  3443. ;                                        (goto-char (point-min))
  3444. ;                                        (end-of-line)
  3445. ;                                        (point))))
  3446. ;      ;; clean the buffer
  3447. ;      (delete-region (point-min) (point-max))
  3448.       ;; send adaname to external process "gnatk8"
  3449.       (call-process "gnatk8" nil krunch-buf nil
  3450.                     adaname ada-krunch-args)
  3451.       ;; fetch output of that process
  3452.       (setq adaname (buffer-substring
  3453.                      (point-min)
  3454.                      (progn
  3455.                        (goto-char (point-min))
  3456.                        (end-of-line)
  3457.                        (point))))
  3458.       (kill-buffer krunch-buf)))
  3459.   (setq adaname adaname) ;; can I avoid this statement?
  3460.   )
  3461.  
  3462.  
  3463. ;;; functions for placing the cursor on the corresponding subprogram
  3464. (defun ada-which-function-are-we-in ()
  3465.   "Determine whether we are on a function definition/declaration and remember
  3466. the name of that function."
  3467.  
  3468.   (setq ff-function-name nil)
  3469.  
  3470.   (save-excursion
  3471.     (if (re-search-backward ada-procedure-start-regexp nil t)
  3472.     (setq ff-function-name (buffer-substring (match-beginning 0)
  3473.                          (match-end 0)))
  3474.       ; we didn't find a procedure start, perhaps there is a package
  3475.       (if (re-search-backward ada-package-start-regexp nil t)
  3476.       (setq ff-function-name (buffer-substring (match-beginning 0)
  3477.                            (match-end 0)))
  3478.     ))))
  3479.  
  3480.  
  3481. ;;;---------------------------------------------------
  3482. ;;; support for imenu
  3483. ;;;---------------------------------------------------
  3484.  
  3485. (defun imenu-create-ada-index (&optional regexp)
  3486.   "create index alist for Ada files."
  3487.   (let ((index-alist '())
  3488.         prev-pos char)
  3489.     (goto-char (point-min))
  3490.     ;(imenu-progress-message prev-pos 0)
  3491.     ;; Search for functions/procedures
  3492.     (save-match-data
  3493.      (while (re-search-forward
  3494.              (or regexp ada-procedure-start-regexp)
  3495.              nil t)
  3496.        ;(imenu-progress-message prev-pos)
  3497.        ;; do not store forward definitions
  3498.        ;; right now we store them. We want to avoid them only in
  3499.        ;; package bodies, not in the specs!! ???RE???
  3500.        (save-match-data
  3501. ;        (if (not (looking-at (concat
  3502. ;                              "[ \t\n]*" ; WS
  3503. ;                              "\([^)]+\)" ; parameterlist
  3504. ;                              "\\([ \n\t]+return[ \n\t]+"; potential return
  3505. ;                              "[a-zA-Z0-9_\\.]+\\)?"
  3506. ;                              "[ \t]*" ; WS
  3507. ;                              ";"  ;; THIS is what we really look for
  3508. ;                              )))
  3509. ;            ; (push (imenu-example--name-and-position) index-alist)
  3510.             (setq index-alist (cons (imenu-example--name-and-position)
  3511.                         index-alist))
  3512. ;          )
  3513.     )
  3514.        ;(imenu-progress-message 100)
  3515.        ))
  3516.     (nreverse index-alist)))
  3517.  
  3518. ;;;---------------------------------------------------
  3519. ;;; support for font-lock
  3520. ;;;---------------------------------------------------
  3521.  
  3522. ;; Strings are a real pain in Ada because both ' and " can appear in a
  3523. ;; non-string quote context (the former as an operator, the latter as
  3524. ;; a character string).  We follow the least losing solution, in which
  3525. ;; only " is a string quote.  Therefore a character string of the form
  3526. ;; '"' will throw fontification off on the wrong track.
  3527.  
  3528. (defconst ada-font-lock-keywords-1
  3529.   (list
  3530.    ;;
  3531.    ;; accept, entry, function, package (body), protected (body|type),
  3532.    ;; pragma, procedure, task (body) plus name.
  3533.    (list (concat
  3534.       "\\<\\("
  3535.       "accept\\|"
  3536.       "entry\\|"
  3537.       "function\\|"
  3538.       "package\\|"
  3539.       "package[ \t]+body\\|"
  3540.       "procedure\\|"
  3541.       "protected\\|"
  3542.       "protected[ \t]+body\\|"
  3543.       "protected[ \t]+type\\|"
  3544. ;;      "p\\(\\(ackage\\|rotected\\)\\(\\|[ \t]+\\(body\\|type\\)\\)\
  3545. ;;\\|r\\(agma\\|ocedure\\)\\)\\|"
  3546.       "task\\|"
  3547.       "task[ \t]+body\\|"
  3548.       "task[ \t]+type"
  3549. ;;      "task\\(\\|[ \t]+body\\)"
  3550.       "\\)\\>[ \t]*"
  3551.       "\\(\\sw+\\(\\.\\sw*\\)*\\)?")
  3552.     '(1 font-lock-keyword-face) '(2 font-lock-function-name-face nil t)))
  3553.   "For consideration as a value of `ada-font-lock-keywords'.
  3554. This does fairly subdued highlighting.")
  3555.  
  3556. (defconst ada-font-lock-keywords-2
  3557.   (append ada-font-lock-keywords-1
  3558.    (list
  3559.     ;;
  3560.     ;; Main keywords, except those treated specially below.
  3561.     (concat "\\<\\("
  3562. ;    ("abort" "abs" "abstract" "accept" "access" "aliased" "all"
  3563. ;     "and" "array" "at" "begin" "case" "declare" "delay" "delta"
  3564. ;     "digits" "do" "else" "elsif" "entry" "exception" "exit" "for"
  3565. ;     "generic" "if" "in" "is" "limited" "loop" "mod" "not"
  3566. ;     "null" "or" "others" "private" "protected"
  3567. ;     "range" "record" "rem" "renames" "requeue" "return" "reverse"
  3568. ;     "select" "separate" "tagged" "task" "terminate" "then" "until"
  3569. ;     "while" "xor")
  3570.             "a\\(b\\(ort\\|s\\(\\|tract\\)\\)\\|cce\\(pt\\|ss\\)\\|"
  3571.             "l\\(iased\\|l\\)\\|nd\\|rray\\|t\\)\\|begin\\|case\\|"
  3572.             "d\\(e\\(clare\\|l\\(ay\\|ta\\)\\)\\|igits\\|o\\)\\|"
  3573.             "e\\(ls\\(e\\|if\\)\\|ntry\\|x\\(ception\\|it\\)\\)\\|for\\|"
  3574.             "generic\\|i[fns]\\|l\\(imited\\|oop\\)\\|mod\\|n\\(ot\\|ull\\)\\|"
  3575.             "o\\(r\\|thers\\|ut\\)\\|pr\\(ivate\\|otected\\)\\|"
  3576.             "r\\(ange\\|e\\(cord\\|m\\|names\\|queue\\|turn\\|verse\\)\\)\\|"
  3577.             "se\\(lect\\|parate\\)\\|"
  3578.             "t\\(agged\\|erminate\\|hen\\)\\|until\\|" ; task removed
  3579.         "wh\\(ile\\|en\\)\\|xor" ; "when" added
  3580.             "\\)\\>")
  3581.     ;;
  3582.     ;; Anything following end and not already fontified is a body name.
  3583.     '("\\<\\(end\\)\\>[ \t]+\\(\\sw+\\)?"
  3584.       (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t))
  3585.     ;;
  3586.     ;; Variable name plus optional keywords followed by a type name.  Slow.
  3587. ;    (list (concat "\\<\\(\\sw+\\)\\>[ \t]*:?[ \t]*"
  3588. ;                 "\\(access\\|constant\\|in\\|in[ \t]+out\\|out\\)?[ \t]*"
  3589. ;                 "\\(\\sw+\\)?")
  3590. ;         '(1 font-lock-variable-name-face)
  3591. ;         '(2 font-lock-keyword-face nil t) '(3 font-lock-type-face nil t))
  3592.     ;;
  3593.     ;; Optional keywords followed by a type name.
  3594.     (list (concat ; ":[ \t]*"
  3595.                   "\\<\\(access\\|constant\\|in\\|in[ \t]+out\\|out\\)\\>"
  3596.                   "[ \t]*"
  3597.                   "\\(\\sw+\\)?")
  3598.           '(1 font-lock-keyword-face nil t) '(2 font-lock-type-face nil t))
  3599.     ;;
  3600.     ;; Keywords followed by a type or function name.
  3601.     (list (concat "\\<\\("
  3602.                   "new\\|of\\|subtype\\|type"
  3603.                   "\\)\\>[ \t]*\\(\\sw+\\)?[ \t]*\\((\\)?")
  3604.           '(1 font-lock-keyword-face)
  3605.           '(2 (if (match-beginning 4)
  3606.                   font-lock-function-name-face
  3607.                 font-lock-type-face) nil t))
  3608.     ;;
  3609.     ;; Keywords followed by a (comma separated list of) reference.
  3610.     (list (concat "\\<\\(goto\\|raise\\|use\\|with\\)\\>" ; "when" removed
  3611.                   ; "[ \t]*\\(\\sw+\\(\\.\\sw*\\)*\\)?") ; RE
  3612.                   "[ \t]*\\([a-zA-Z0-9_\\.\\|, ]+\\)\\W")
  3613.           '(1 font-lock-keyword-face) '(2 font-lock-reference-face nil t))
  3614.     ;;
  3615.     ;; Goto tags.
  3616.     '("<<\\(\\sw+\\)>>" 1 font-lock-reference-face)
  3617.     ))
  3618.   "For consideration as a value of `ada-font-lock-keywords'.
  3619. This does a lot more highlighting.")
  3620.  
  3621. (defvar ada-font-lock-keywords (if font-lock-use-maximal-decoration
  3622.                    ada-font-lock-keywords-2
  3623.                  ada-font-lock-keywords-1)
  3624.   "*Expressions to highlight in Ada mode.")
  3625.  
  3626. ;;;
  3627. ;;; ????
  3628. ;;;
  3629. (defun ada-gen-comment-until-proc ()
  3630.   ;; comment until spec of a procedure or a function.
  3631.   (forward-line 1)
  3632.   (set-mark-command (point))
  3633.   (if (re-search-forward ada-procedure-start-regexp nil t)
  3634.       (progn (goto-char (match-beginning 1))
  3635.              (comment-region (mark) (point)))
  3636.     (error "No more functions/procedures")))
  3637.  
  3638.  
  3639. (defun ada-gen-treat-proc (match)
  3640.   ;; make dummy body of a procedure/function specification.
  3641.   ;; MATCH is a cons cell containing the start and end location of the
  3642.   ;; last search for ada-procedure-start-regexp. 
  3643.   (goto-char (car match))
  3644.   (let (proc-found func-found)
  3645.     (cond
  3646.      ((or (setq proc-found (looking-at "^[ \t]*procedure"))
  3647.       (setq func-found (looking-at "^[ \t]*function")))
  3648.       ;; treat it as a proc/func
  3649.       (forward-word 2) 
  3650.       (forward-word -1)
  3651.       (setq procname (buffer-substring (point) (cdr match))) ; store  proc name
  3652.  
  3653.     ;; goto end of procname
  3654.     (goto-char (cdr match))
  3655.  
  3656.     ;; skip over parameterlist
  3657.     (forward-sexp)
  3658.     ;; if function, skip over 'return' and result type.
  3659.     (if func-found
  3660.     (progn
  3661.       (forward-word 1)
  3662.       (skip-chars-forward " \t\n")
  3663.       (setq functype (buffer-substring (point)
  3664.                        (progn 
  3665.                          (skip-chars-forward
  3666.                           "a-zA-Z0-9_\.")
  3667.                          (point))))))
  3668.     ;; look for next non WS
  3669.     (cond
  3670.      ((looking-at "[ \t]*;")
  3671.       (delete-region (match-beginning 0) (match-end 0)) ;; delete the ';'
  3672.       (ada-indent-newline-indent)
  3673.       (insert " is")
  3674.       (ada-indent-newline-indent)
  3675.       (if func-found
  3676.       (progn
  3677.         (insert "Result : ")
  3678.         (insert functype)
  3679.         (insert ";")
  3680.         (ada-indent-newline-indent)))
  3681.       (insert "begin -- ")
  3682.       (insert procname)
  3683.       (ada-indent-newline-indent)
  3684.       (insert "null;")
  3685.       (ada-indent-newline-indent)
  3686.       (if func-found
  3687.       (progn
  3688.         (insert "return Result;")
  3689.         (ada-indent-newline-indent)))
  3690.       (insert "end ")
  3691.       (insert procname)
  3692.       (insert ";")
  3693.       (ada-indent-newline-indent)    
  3694.       )
  3695.       ;; else
  3696.      ((looking-at "[ \t\n]*is")
  3697.       ;; do nothing
  3698.       )
  3699.      ((looking-at "[ \t\n]*rename")
  3700.       ;; do nothing
  3701.       )
  3702.      (t
  3703.       (message "unknown syntax")))
  3704.     ))))
  3705.  
  3706.  
  3707. (defun ada-make-body ()
  3708.   "Create an Ada package body in the current buffer.
  3709. The potential old buffer contents is deleted first, then we copy the
  3710. spec buffer in here and modify it to make it a body.
  3711.  
  3712. This function typically is to be hooked into `ff-file-created-hooks'."
  3713.   (interactive)
  3714.   (delete-region (point-min) (point-max))
  3715.   (insert-buffer (car (cdr (buffer-list))))
  3716.   (ada-mode)
  3717.  
  3718.   (let (found)
  3719.     (if (setq found 
  3720.           (ada-search-ignore-string-comment ada-package-start-regexp))
  3721.     (progn (goto-char (cdr found))
  3722.            (insert " body")
  3723.            ;; (forward-line -1)
  3724.            ;;(comment-region (point-min) (point))
  3725.            )
  3726.       (error "No package"))
  3727.     
  3728.     ;; (comment-until-proc)
  3729.     ;;   does not work correctly
  3730.     ;;   must be done by hand
  3731.     
  3732.     (while (setq found
  3733.          (ada-search-ignore-string-comment ada-procedure-start-regexp))
  3734.       (ada-gen-treat-proc found))))
  3735.  
  3736.  
  3737. ;;; provide ourself
  3738.  
  3739. (provide 'ada-mode)
  3740.  
  3741. ;;; ada-mode.el ends here
  3742.